From 1f6733d91d218e51e8998cf378af6c366d3dbd0d Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@Germany> Date: Fri, 30 Jan 2009 00:07:53 +0100 Subject: [PATCH] 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. --- applications/test/PackedList/PackedListTest.C | 57 +++- .../containers/Lists/PackedList/PackedList.C | 51 +-- .../containers/Lists/PackedList/PackedList.H | 93 +++--- .../containers/Lists/PackedList/PackedListI.H | 301 +++++++----------- 4 files changed, 229 insertions(+), 273 deletions(-) diff --git a/applications/test/PackedList/PackedListTest.C b/applications/test/PackedList/PackedListTest.C index f1f58f3abca..a8488eb1836 100644 --- a/applications/test/PackedList/PackedListTest.C +++ b/applications/test/PackedList/PackedListTest.C @@ -52,13 +52,25 @@ int main(int argc, char *argv[]) list1 = -1; 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"; list1[2] = 3; list1[4] = list1[2]; list1.print(Info); 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); { @@ -91,6 +103,14 @@ int main(int argc, char *argv[]) list1.resize(8, list1.max_value()); 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"; list1.set(1, 5); list1.print(Info); @@ -188,15 +208,23 @@ int main(int argc, char *argv[]) { Info<< "\ntest assignment of iterator\n"; list1.print(Info); - PackedList<3>::iterator cit = list1[25]; - cit.print(Info); + Info<< "cend()\n"; 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 ( - PackedList<3>::iterator cit = list1[5]; + PackedList<3>::iterator cit = list1[30]; cit != list1.end(); ++cit ) @@ -204,14 +232,19 @@ int main(int argc, char *argv[]) cit.print(Info); } -// Info<< "\ntest operator[] auto-vivify\n"; -// const unsigned int val = list1[45]; -// -// Info<< "list[45]:" << val << "\n"; -// list1[45] = list1.max_value(); -// Info<< "list[45]:" << list1[45] << "\n"; -// list1[49] = list1.max_value(); -// list1.print(Info); + Info<< "\ntest operator[] auto-vivify\n"; + Info<< "size:" << list1.size() << "\n"; + + const unsigned int val = list1[45]; + + Info<< "list[45]:" << val << "\n"; + Info<< "size after read:" << list1.size() << "\n"; + + 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"; diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedList.C b/src/OpenFOAM/containers/Lists/PackedList/PackedList.C index 8667ad47ba5..87ced9504f8 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedList.C +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedList.C @@ -83,25 +83,25 @@ unsigned int Foam::PackedList<nBits>::count() const if (size_) { - // mask value for complete chunks + // mask value for complete segments unsigned int mask = maskLower(packing()); - unsigned int endIdx = size_ / packing(); - unsigned int endOff = size_ % packing(); + const unsigned int endSeg = size_ / packing(); + const unsigned int endOff = size_ % packing(); - // count bits in complete elements - for (unsigned i = 0; i < endIdx; ++i) + // count bits in complete segments + for (unsigned i = 0; i < endSeg; ++i) { register unsigned int bits = StorageList::operator[](i) & mask; COUNT_PACKEDBITS(c, bits); } - // count bits in partial chunk + // count bits in partial segment if (endOff) { mask = maskLower(endOff); - register unsigned int bits = StorageList::operator[](endIdx) & mask; + register unsigned int bits = StorageList::operator[](endSeg) & mask; COUNT_PACKEDBITS(c, bits); } } @@ -118,7 +118,7 @@ bool Foam::PackedList<nBits>::trim() return false; } - // mask value for complete chunks + // mask value for complete segments unsigned int mask = maskLower(packing()); label currElem = packedLength(size_) - 1; @@ -130,7 +130,7 @@ bool Foam::PackedList<nBits>::trim() StorageList::operator[](currElem) &= maskLower(endOff); } - // test entire chunk + // test entire segment while (currElem > 0 && !(StorageList::operator[](currElem) &= mask)) { 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> Foam::labelList Foam::PackedList<nBits>::values() const { - labelList elems(size()); + labelList elems(size_); forAll(*this, i) { @@ -178,10 +190,11 @@ Foam::labelList Foam::PackedList<nBits>::values() const template<unsigned nBits> Foam::Ostream& Foam::PackedList<nBits>::iteratorBase::print(Ostream& os) const { - os << "iterator<" << label(nBits) << "> [" - << (index_ * packing() + offset_) << "]" - << " index:" << index_ << " offset:" << offset_ - << " value:" << unsigned(*this) + os << "iterator<" << label(nBits) << "> [" + << this->index_ << "]" + << " segment:" << label(this->index_ / packing()) + << " offset:" << label(this->index_ % packing()) + << " value:" << this->get() << nl; return os; @@ -194,7 +207,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const os << "PackedList<" << label(nBits) << ">" << " max_value:" << max_value() << " packing:" << packing() << nl - << "values: " << size() << "/" << capacity() << "( "; + << "values: " << size_ << "/" << capacity() << "( "; forAll(*this, i) { os << get(i) << ' '; @@ -205,17 +218,17 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const os << ")\n" << "storage: " << packLen << "/" << StorageList::size() << "( "; - // mask value for complete chunks + // mask value for complete segments unsigned int mask = maskLower(packing()); for (label i=0; i < packLen; 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) { - unsigned endOff = size_ % packing(); + unsigned int endOff = size_ % packing(); 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) { - if (testBit & mask) + if (mask & testBit) { if (rawBits & testBit) { diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedList.H b/src/OpenFOAM/containers/Lists/PackedList/PackedList.H index b65a658e3a3..a9cd59da86c 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedList.H +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedList.H @@ -44,9 +44,9 @@ Note Using the iteratorBase as a proxy allows assignment of values between list elements. Thus the following bit of code works as expected: @code - blist[1] = blist[5]; // value assignment, not iterator position - blist[2] = blist[5] = 4; // propagates value - blist[1] = blist[5] = blist[6]; // propagates value + list[1] = list[5]; // value assignment, not iterator position + list[2] = list[5] = 4; // propagates value + list[1] = list[5] = list[6]; // propagates value @endcode Using get() or the '[]' operator are similarly fast. Looping and reading @@ -58,11 +58,21 @@ Note useful for branching on changed values. @code - blist[5] = 4; - changed = blist.set(5, 8); + list[5] = 4; + changed = list.set(5, 8); if (changed) ... @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 Foam::DynamicList @@ -120,9 +130,6 @@ class PackedList //- Calculate the list length when packed inline static label packedLength(const label); - //- Check index I is within valid range [ 0 .. max_value() ] - inline void checkIndex(const label) const; - public: // Public data @@ -172,22 +179,23 @@ public: // 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; //- Number of entries. 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; //- Get value at index I. - // Does not auto-vivify entries. + // Never auto-vivify entries. inline unsigned int get(const label) const; //- Set value at index I. Return true if value changed. - // Does not auto-vivify entries. - inline bool set(const label, const unsigned int val); + // Does auto-vivify for non-existent entries. + // Default value set is the max_value. + inline bool set(const label, const unsigned int val = ~0u); //- Return the underlying packed storage inline List<unsigned int>& storage(); @@ -200,9 +208,6 @@ public: // http://en.wikipedia.org/wiki/Hamming_weight unsigned int count() const; - //- Trim any trailing zero elements - bool trim(); - //- Return the values as a labelList labelList values() const; @@ -211,6 +216,12 @@ public: // Edit + //- Trim any trailing zero elements + bool trim(); + + //- Invert the bits in the addressable region. + void flip(); + //- Alter the size of the underlying storage. // The addressed size will be truncated if needed to fit, but will // remain otherwise untouched. @@ -255,12 +266,12 @@ public: inline unsigned int remove(); //- Get value at index I - // Does not auto-vivify entries. + // Never auto-vivify entries. inline unsigned int operator[](const label) const; //- Set value at index I. // 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); //- 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 PackedList* list_; - //- Element index within storage - unsigned index_; - - //- Offset within storage element - unsigned offset_; + //- Element index + label index_; // Protected Member Functions - //- Get value as unsigned + //- Get value as unsigned, no range-checking 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); - //- 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 //- Construct null inline iteratorBase(); - //- Copy construct - inline iteratorBase(const iteratorBase&); - //- Construct from base list and position index inline iteratorBase(const PackedList*, const label); 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 //- Compare positions @@ -350,10 +336,12 @@ public: // This allows packed[0] = packed[3] for assigning values 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); //- Conversion operator + // Never auto-vivify entries. inline operator unsigned int () const; //- Print value and information @@ -378,6 +366,8 @@ public: inline iterator(); //- 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&); //- Construct from base list and position index @@ -386,6 +376,7 @@ public: // Member Operators //- Assign from iteratorBase, eg iter = packedlist[i] + // An out-of-range iterator is assigned end() inline iterator& operator=(const iteratorBase&); //- Return value @@ -427,7 +418,9 @@ public: //- Construct null 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&); //- Construct from base list and position index @@ -439,7 +432,7 @@ public: // Member operators //- 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&); //- Return referenced value directly diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H b/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H index 07e6d062083..929688ef242 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H @@ -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 * * * * * * * * * * * * * * // template<unsigned nBits> @@ -105,7 +87,7 @@ template<unsigned nBits> inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst) : StorageList(lst), - size_(lst.size()) + size_(lst.size_) {} @@ -132,20 +114,7 @@ template<unsigned nBits> inline Foam::PackedList<nBits>::iteratorBase::iteratorBase() : list_(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_) + index_(0) {} @@ -157,8 +126,7 @@ inline Foam::PackedList<nBits>::iteratorBase::iteratorBase ) : list_(const_cast<PackedList<nBits>*>(lst)), - index_(i / packing()), - offset_(i % packing()) + index_(i) {} @@ -166,8 +134,11 @@ template<unsigned nBits> inline unsigned int Foam::PackedList<nBits>::iteratorBase::get() const { - const unsigned int& stored = list_->StorageList::operator[](index_); - return (stored >> (nBits * offset_)) & max_value(); + const unsigned int seg = index_ / packing(); + 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 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 startBit = nBits * offset_; + const unsigned int startBit = nBits * off; const unsigned int maskNew = max_value() << startBit; if (val & ~max_value()) { -# ifdef DEBUGList - 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 + // overflow is max_value, fill everything stored |= maskNew; } else { - stored = (stored & ~maskNew) | (maskNew & (val << startBit)); + stored &= ~maskNew; + stored |= maskNew & (val << startBit); } 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> inline bool Foam::PackedList<nBits>::iteratorBase::operator== ( const iteratorBase& iter ) 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 { - return this->index_ != iter.index_ || this->offset_ != iter.offset_; + return this->index_ != iter.index_; } @@ -310,14 +204,11 @@ template<unsigned nBits> inline unsigned int Foam::PackedList<nBits>::iteratorBase::operator=(const unsigned int val) { -# ifdef DEBUGList - // lazy evaluation would be nice to keep, but really slows things down - label minsize = 1 + offset_ + index_ * packing(); - if (minsize > list_->size_) + // lazy evaluation - increase size on assigment + if (index_ >= list_->size_) { - list_->resize(minsize); + list_->resize(index_ + 1); } -#endif this->set(val); return val; @@ -328,14 +219,11 @@ template<unsigned nBits> inline Foam::PackedList<nBits>::iteratorBase::operator unsigned int () const { -# ifdef DEBUGList - // lazy evaluation would be nice to keep, but really slows things down - label minsize = 1 + offset_ + index_ * packing(); - if (minsize > list_->size_) + // lazy evaluation - return 0 for out-of-range + if (index_ >= list_->size_) { return 0; } -#endif return this->get(); } @@ -365,7 +253,12 @@ inline Foam::PackedList<nBits>::iterator::iterator : 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) { - 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& 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; } @@ -426,7 +333,16 @@ template<unsigned nBits> inline typename Foam::PackedList<nBits>::const_iterator& 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; } @@ -435,7 +351,7 @@ template<unsigned nBits> inline typename Foam::PackedList<nBits>::iterator& Foam::PackedList<nBits>::iterator::operator++() { - this->incr(); + ++this->index_; return *this; } @@ -444,7 +360,7 @@ template<unsigned nBits> inline typename Foam::PackedList<nBits>::const_iterator& Foam::PackedList<nBits>::const_iterator::operator++() { - this->incr(); + ++this->index_; return *this; } @@ -454,7 +370,7 @@ inline typename Foam::PackedList<nBits>::iterator Foam::PackedList<nBits>::iterator::operator++(int) { iterator old = *this; - this->incr(); + ++this->index_; return old; } @@ -464,7 +380,7 @@ inline typename Foam::PackedList<nBits>::const_iterator Foam::PackedList<nBits>::const_iterator::operator++(int) { const_iterator old = *this; - this->incr(); + ++this->index_; return old; } @@ -473,7 +389,7 @@ template<unsigned nBits> inline typename Foam::PackedList<nBits>::iterator& Foam::PackedList<nBits>::iterator::operator--() { - this->decr(); + --this->index_; return *this; } @@ -482,7 +398,7 @@ template<unsigned nBits> inline typename Foam::PackedList<nBits>::const_iterator& Foam::PackedList<nBits>::const_iterator::operator--() { - this->decr(); + --this->index_; return *this; } @@ -492,7 +408,7 @@ inline typename Foam::PackedList<nBits>::iterator Foam::PackedList<nBits>::iterator::operator--(int) { iterator old = *this; - this->decr(); + --this->index_; return old; } @@ -502,7 +418,7 @@ inline typename Foam::PackedList<nBits>::const_iterator Foam::PackedList<nBits>::const_iterator::operator--(int) { const_iterator old = *this; - this->decr(); + --this->index_; return old; } @@ -567,7 +483,7 @@ template<unsigned nBits> inline typename Foam::PackedList<nBits>::iterator 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 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 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 if (size_) { - // fill value for complete chunks + // fill value for complete segments 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 everything + // overflow is max_value, fill everything fill = ~0; } else @@ -641,26 +549,26 @@ inline void Foam::PackedList<nBits>::resize } } - unsigned begIdx = size_ / packing(); - unsigned begOff = size_ % packing(); - unsigned endIdx = nElem / packing(); + unsigned int seg = size_ / packing(); + unsigned int off = size_ % packing(); - // partial chunk, preserve existing value - if (begOff) + // partial segment, preserve existing value + if (off) { - unsigned int maskOld = maskLower(begOff); + unsigned int maskOld = maskLower(off); - StorageList::operator[](begIdx) &= maskOld; - StorageList::operator[](begIdx) |= ~maskOld & fill; + StorageList::operator[](seg) &= maskOld; + StorageList::operator[](seg) |= ~maskOld & fill; - // continue with the next chunk - begIdx++; + // continue with the next segment + seg++; } + unsigned int endSeg = nElem / packing(); // fill in complete elements - while (begIdx < endIdx) + while (seg < endSeg) { - StorageList::operator[](begIdx++) = fill; + StorageList::operator[](seg++) = fill; } } else @@ -786,17 +694,31 @@ Foam::PackedList<nBits>::xfer() template<unsigned nBits> inline unsigned int Foam::PackedList<nBits>::get(const label i) const { -# ifdef DEBUGList - checkIndex(i); +# ifdef FULLDEBUG + if (i < 0) + { + FatalErrorIn("PackedList<nBits>::get(const label)") + << "negative index " << i << " max=" << size_-1 + << abort(FatalError); + } # endif - return iteratorBase(this, i).get(); + // lazy evaluation - return 0 for out-of-range + if (i < size_) + { + return iteratorBase(this, i).get(); + } + else + { + return 0; + } } template<unsigned nBits> inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const { + // lazy evaluation - return 0 for out-of-range if (i < size_) { return iteratorBase(this, i).get(); @@ -815,18 +737,21 @@ inline bool Foam::PackedList<nBits>::set const unsigned int val ) { -# ifdef DEBUGList - checkIndex(i); - - if (val & ~max_value()) +# ifdef FULLDEBUG + if (i < 0) { - FatalErrorIn("PackedList<T>::set(const label, const unsigned int)") - << "value " << label(val) - << " out-of-range 0 ... " << label(max_value()) - << " representable by " << nBits << " bits" + FatalErrorIn("PackedList<nBits>::set(const label)") + << "negative index " << i << " max=" << size_-1 << abort(FatalError); } -# endif +#endif + + // lazy evaluation - increase size on assigment + if (i >= size_) + { + resize(i + 1); + } + return iteratorBase(this, i).set(val); } @@ -879,14 +804,6 @@ inline void Foam::PackedList<nBits>::operator=(const unsigned int val) 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 = ~0; } -- GitLab