PackedList gets count() and trim() methods

- the bit counting is relatively fast:
  under 0.2 seconds for 1M bits counted 1000 times

- trim()'ing the final zero elements tested for a few cases,
  but might need more attention
This commit is contained in:
Mark Olesen
2009-01-28 16:32:47 +01:00
parent 22df173acb
commit 7c739978b1
7 changed files with 429 additions and 174 deletions

View File

@ -38,7 +38,6 @@ using namespace Foam;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
bool changed;
Info<< "PackedList max_bits() = " << PackedList<0>::max_bits() << nl; Info<< "PackedList max_bits() = " << PackedList<0>::max_bits() << nl;
Info<< "\ntest allocation with value\n"; Info<< "\ntest allocation with value\n";
@ -46,7 +45,42 @@ int main(int argc, char *argv[])
list1.print(Info); list1.print(Info);
Info<< "\ntest assign uniform value\n"; Info<< "\ntest assign uniform value\n";
list1 = 4; list1 = 3;
list1.print(Info);
Info<< "\ntest assign uniform value (with overflow)\n";
list1 = -1;
list1.print(Info);
Info<< "\ntest assign between references - does not work as expected\n";
list1[2] = 3;
list1[4] = list1[2];
list1.print(Info);
{
const PackedList<3>& constLst = list1;
Info<< "\ntest operator[] const with out-of-range index\n";
constLst.print(Info);
if (!constLst[20])
{
Info<< "[20] is false, as expected\n";
}
constLst.print(Info);
Info<< "\ntest operator[] non-const with out-of-range index\n";
if (!list1[20])
{
Info<< "[20] is false, as expected but list was resized!! (non-const)\n";
}
list1.print(Info);
}
Info<< "\ntest operator[] with out-of-range index\n";
if (!list1[20])
{
Info<< "[20] is false, as expected\n";
}
list1.print(Info); list1.print(Info);
Info<< "\ntest resize with value (without reallocation)\n"; Info<< "\ntest resize with value (without reallocation)\n";
@ -111,6 +145,10 @@ int main(int argc, char *argv[])
list1.setCapacity(24); list1.setCapacity(24);
list1.print(Info); list1.print(Info);
Info<< "\ntest trim\n";
list1.trim();
list1.print(Info);
// add in some misc values // add in some misc values
list1[31] = 1; list1[31] = 1;
list1[32] = 2; list1[32] = 2;
@ -122,12 +160,10 @@ int main(int argc, char *argv[])
iter.print(Info) << "\n"; iter.print(Info) << "\n";
Info<< "\ntest iterator operator=\n"; Info<< "\ntest iterator operator=\n";
changed = (iter = 5); iter = 2;
Info<< "iterator:" << iter() << "\n"; Info<< "iterator:" << iter() << "\n";
Info<< "changed:" << changed << "\n"; iter = 5;
changed = (iter = 5);
Info<< "changed:" << changed << "\n";
list1.print(Info); list1.print(Info);
Info<< "\ntest get() method\n"; Info<< "\ntest get() method\n";
@ -137,12 +173,13 @@ int main(int argc, char *argv[])
Info<< "\ntest iterator indexing\n"; Info<< "\ntest iterator indexing\n";
Info<< "cend() "; Info<< "cend() ";
list1.cend().print(Info) << "\n"; list1.cend().print(Info) << "\n";
for for
( (
PackedList<3>::const_iterator cit = list1[30]; PackedList<3>::const_iterator cit = list1[30];
cit != list1.cend(); cit != list1.cend();
++cit) ++cit
)
{ {
cit.print(Info); cit.print(Info);
} }
@ -167,7 +204,7 @@ int main(int argc, char *argv[])
Info<< "\ntest pattern that fills all bits\n"; Info<< "\ntest pattern that fills all bits\n";
PackedList<4> list3(8, 8); PackedList<4> list3(8, 8);
label pos = list3.size() - 1; label pos = list3.size() - 1;
list3[pos--] = list3.max_value(); list3[pos--] = list3.max_value();

View File

@ -54,7 +54,7 @@ int main(int argc, char *argv[])
std::vector<bool> stlVector(n, true); std::vector<bool> stlVector(n, true);
labelHashSet emptyHash; labelHashSet emptyHash;
labelHashSet fullHash; labelHashSet fullHash(1000);
for(label i = 0; i < n; i++) for(label i = 0; i < n; i++)
{ {
fullHash.insert(i); fullHash.insert(i);
@ -70,6 +70,35 @@ int main(int argc, char *argv[])
} }
Info<< "resize/shrink/resize:" << timer.cpuTimeIncrement() << " s\n\n"; Info<< "resize/shrink/resize:" << timer.cpuTimeIncrement() << " s\n\n";
// set every other bit on:
Info<< "set every other bit on and count\n";
packed.storage() = 0xAAAAAAAAu;
// Count packed
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
forAll(packed, i)
{
sum += packed[i];
}
}
Info<< "Counting brute-force:" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
// Count packed
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
sum += packed.count();
}
Info<< "Counting via count():" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
// Dummy addition // Dummy addition
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; iter++)
@ -182,7 +211,7 @@ int main(int argc, char *argv[])
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; iter++)
{ {
forAll(packed, i) forAll(unpacked, i)
{ {
sum += emptyHash.found(i); sum += emptyHash.found(i);
} }
@ -196,7 +225,7 @@ int main(int argc, char *argv[])
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; iter++)
{ {
forAll(packed, i) forAll(unpacked, i)
{ {
sum += fullHash.found(i); sum += fullHash.found(i);
} }
@ -206,7 +235,6 @@ int main(int argc, char *argv[])
Info<< " sum " << sum << endl; Info<< " sum " << sum << endl;
// //
// Write // Write
// //
@ -326,8 +354,7 @@ int main(int argc, char *argv[])
Info<< "Writing packed<3> uniform 1:" << timer.cpuTimeIncrement() Info<< "Writing packed<3> uniform 1:" << timer.cpuTimeIncrement()
<< " s" << endl; << " s" << endl;
Info << "End\n" << endl; Info << "End\n" << endl;
return 0; return 0;

View File

@ -50,7 +50,7 @@ primitives/random/Random.C
containers/HashTables/HashTable/HashTableName.C containers/HashTables/HashTable/HashTableName.C
containers/HashTables/StaticHashTable/StaticHashTableName.C containers/HashTables/StaticHashTable/StaticHashTableName.C
containers/Lists/SortableList/ParSortableListName.C containers/Lists/SortableList/ParSortableListName.C
containers/Lists/PackedList/PackedListName.C containers/Lists/PackedList/PackedListCore.C
containers/Lists/ListOps/ListOps.C containers/Lists/ListOps/ListOps.C
containers/LinkedLists/linkTypes/SLListBase/SLListBase.C containers/LinkedLists/linkTypes/SLListBase/SLListBase.C
containers/LinkedLists/linkTypes/DLListBase/DLListBase.C containers/LinkedLists/linkTypes/DLListBase/DLListBase.C

View File

@ -53,6 +53,115 @@ Foam::PackedList<nBits>::PackedList(const UList<label>& lst)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
#if (UINT_MAX == 0xFFFFFFFF)
// 32-bit counting, Hamming weight method
# define COUNT_PACKEDBITS(sum, x) \
{ \
x -= (x >> 1) & 0x55555555; \
x = (x & 0x33333333) + ((x >> 2) & 0x33333333); \
sum += (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; \
}
#elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
// 64-bit counting, Hamming weight method
# define COUNT_PACKEDBITS(sum, x) \
{ \
x -= (x >> 1) & 0x5555555555555555; \
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); \
sum += (((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101) >> 56;\
}
#else
// Arbitrary number of bits, Brian Kernighan's method
# define COUNT_PACKEDBITS(sum, x) for (; x; ++sum) { x &= x - 1; }
#endif
template<int nBits>
unsigned int Foam::PackedList<nBits>::count() const
{
register unsigned int c = 0;
if (size_)
{
// mask value for complete chunks
unsigned int mask = (0x1 << (nBits * packing())) - 1;
unsigned int endIdx = size_ / packing();
unsigned int endOff = size_ % packing();
// count bits in complete elements
for (unsigned i = 0; i < endIdx; ++i)
{
register unsigned int bits = StorageList::operator[](i) & mask;
COUNT_PACKEDBITS(c, bits);
}
// count bits in partial chunk
if (endOff)
{
mask = (0x1 << (nBits * endOff)) - 1;
register unsigned int bits = StorageList::operator[](endIdx) & mask;
COUNT_PACKEDBITS(c, bits);
}
}
return c;
}
template<int nBits>
bool Foam::PackedList<nBits>::trim()
{
if (!size_)
{
return false;
}
// mask value for complete chunks
unsigned int mask = (0x1 << (nBits * packing())) - 1;
label currElem = packedLength(size_) - 1;
unsigned int endOff = size_ % packing();
// clear trailing bits on final segment
if (endOff)
{
StorageList::operator[](currElem) &= ((0x1 << (nBits * endOff)) - 1);
}
// test entire chunk
while (currElem > 0 && !(StorageList::operator[](currElem) &= mask))
{
currElem--;
}
// test segment
label newsize = (currElem + 1) * packing();
// mask for the final segment
mask = max_value() << (nBits * (packing() - 1));
for (endOff = packing(); endOff >= 1; --endOff, --newsize)
{
if (StorageList::operator[](currElem) & mask)
{
break;
}
mask >>= nBits;
}
if (size_ == newsize)
{
return false;
}
size_ = newsize;
return false;
}
template<int nBits> template<int nBits>
Foam::labelList Foam::PackedList<nBits>::values() const Foam::labelList Foam::PackedList<nBits>::values() const
{ {
@ -91,41 +200,36 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
os << get(i) << ' '; os << get(i) << ' ';
} }
label packLen = packedLength(size()); label packLen = packedLength(size_);
os << ")\n" os << ")\n"
<< "storage: " << packLen << "/" << StorageList::size() << "( "; << "storage: " << packLen << "/" << StorageList::size() << "( ";
// mask for the valid bits // mask value for complete chunks
unsigned int validBits = max_value(); unsigned int mask = (0x1 << (nBits * packing())) - 1;
for (unsigned int i = 1; i < packing(); ++i)
{
validBits |= (validBits << nBits);
}
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 validBits accordingly // the final storage may not be full, modify mask accordingly
if (i+1 == packLen) if (i+1 == packLen)
{ {
label junk = size() % packing(); unsigned endOff = size_ % packing();
if (junk) if (endOff)
{ {
junk = packing() - junk; mask = (0x1 << (nBits * endOff)) - 1;
} }
else
for (label j=0; j < junk; j++)
{ {
validBits >>= nBits; continue;
} }
} }
for (unsigned int testBit = 0x1 << max_bits(); testBit; testBit >>= 1) for (unsigned int testBit = 0x1 << max_bits(); testBit; testBit >>= 1)
{ {
if (testBit & validBits) if (testBit & mask)
{ {
if (rawBits & testBit) if (rawBits & testBit)
{ {

View File

@ -37,16 +37,20 @@ Description
Note Note
The iterator '()' dereferencing operator returns a proxy class that handles The iterator '()' dereferencing operator returns a proxy class that handles
assignment. However, the iterator itself can also handle assignment assignment. However, the iterator itself can also handle assignment
directly and also returns a bool as per the set() methods. directly, but does not return anything.
Thus the following bit of code works as expected: Thus the following bit of code works as expected:
@code @code
blist[5] = 4; blist[5] = 4;
changed = (blist[5] = 10);
changed = blist.set(5, 8); changed = blist.set(5, 8);
changed = (blist[5] = 1); // ERROR - operator= is 'void'
@endcode @endcode
Using set() might be more readable (as expected) though. Making the assignment operator void prevents people from trying this type
of thing:
@code
blist[2] = blist[5] = 4; // bad idea, thus ERROR - operator= is 'void'
blist[1] = blist[5]; // iterator not value assignment!
@endcode
SeeAlso SeeAlso
Foam::DynamicList Foam::DynamicList
@ -171,9 +175,20 @@ public:
// Does not auto-vivify entries. // Does not auto-vivify entries.
inline bool set(const label, const unsigned int val); inline bool set(const label, const unsigned int val);
//- Return the underlying packed storage
inline List<unsigned int>& storage();
//- Return the underlying packed storage //- Return the underlying packed storage
inline const List<unsigned int>& storage() const; inline const List<unsigned int>& storage() const;
//- Count number of bits set, O(log(n))
// Uses the Hamming weight (population count) method
// http://en.wikipedia.org/wiki/Hamming_weight
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;
@ -216,6 +231,7 @@ public:
//- Transfer contents to the Xfer container //- Transfer contents to the Xfer container
inline Xfer<PackedList<nBits> > xfer(); inline Xfer<PackedList<nBits> > xfer();
// Member operators // Member operators
//- Append a value at the end of the list //- Append a value at the end of the list
@ -244,144 +260,148 @@ public:
// Ostream operator // Ostream operator
// // Write PackedList to Ostream. // // Write PackedList to Ostream.
// 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: data and functions are 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 and used by iterator. // just inherited and used by iterator.
class const_iterator class const_iterator
{
friend class PackedList;
protected:
// Protected Data
//- Pointer to original list
// This also lets us use the default bitwise copy/assignment
PackedList* list_;
//- Element index within storage
unsigned index_;
//- Offset within storage element
unsigned offset_;
// Protected Member Functions
//- Get value as unsigned
inline unsigned int get() const;
//- Set value, returning true if changed
// This is obviously used by iterator and not by const_iterator
inline bool set(unsigned int);
public:
// Constructors
//- Construct from base list and position index
inline const_iterator(const PackedList*, const label);
//- Construct from non-const iterator
explicit inline const_iterator(const iterator&);
// Member operators
inline bool operator==(const const_iterator&) const;
inline bool operator!=(const const_iterator&) const;
//- Return referenced value directly
inline unsigned int operator*() const;
//- Return referenced value directly
inline unsigned int operator()() const;
inline const_iterator& operator++();
inline const_iterator operator++(int);
//- Conversion operator
inline operator unsigned int () const;
//- Print value and information
Ostream& print(Ostream&) const;
};
//- const_iterator set to the beginning of the PackedList
inline const_iterator cbegin() const;
//- const_iterator set to beyond the end of the PackedList
inline const_iterator cend() const;
//- const_iterator set to the beginning of the PackedList
inline const_iterator begin() const;
//- const_iterator set to beyond the end of the PackedList
inline const_iterator end() const;
//- The iterator class used for PackedList
class iterator
:
public const_iterator
{
friend class PackedList;
//- A private proxy reference to the iterator, used for setting values
// Also provides a uniform target for the iterator 'operator*'
// and 'operator()' methods
class iteratorProxy
{ {
iterator* iter_; friend class PackedList;
protected:
// Protected Data
//- Pointer to original list
// This also lets us use the default bitwise copy/assignment
PackedList* list_;
//- Element index within storage
unsigned index_;
//- Offset within storage element
unsigned offset_;
// Protected Member Functions
//- Get value as unsigned
inline unsigned int get() const;
//- Set value, returning true if changed
// This is obviously used by iterator and not by const_iterator
inline bool set(unsigned int);
public: public:
//- Construct from pointer to iterator // Constructors
inline iteratorProxy(iterator*);
//- Assign value, returns true if the value changed //- Construct from base list and position index
inline bool operator=(const unsigned int val); inline const_iterator(const PackedList*, const label);
//- Construct from non-const iterator
explicit inline const_iterator(const iterator&);
// Member operators
inline bool operator==(const const_iterator&) const;
inline bool operator!=(const const_iterator&) const;
//- Return referenced value directly
inline unsigned int operator*() const;
//- Return referenced value directly
inline unsigned int operator()() const;
inline const_iterator& operator++();
inline const_iterator operator++(int);
inline const_iterator& operator--();
inline const_iterator operator--(int);
//- Conversion operator //- Conversion operator
inline operator unsigned int () const; inline operator unsigned int () const;
//- Print value and information
Ostream& print(Ostream&) const;
}; };
public:
// Constructors //- const_iterator set to the beginning of the PackedList
inline const_iterator cbegin() const;
//- Construct from base list and position index //- const_iterator set to beyond the end of the PackedList
inline iterator(const PackedList*, const label); inline const_iterator cend() const;
// Member Operators //- const_iterator set to the beginning of the PackedList
inline void operator=(const iterator&); inline const_iterator begin() const;
//- Assign value directly, returns true if the value changed //- const_iterator set to beyond the end of the PackedList
inline bool operator=(unsigned int); inline const_iterator end() const;
//- Return value
inline unsigned int operator*() const;
//- Return value //- The iterator class used for PackedList
inline unsigned int operator()() const; class iterator
:
public const_iterator
{
friend class PackedList;
//- Return proxy for assigning the referenced value //- A proxy reference to the iterator, used for setting values.
inline iteratorProxy operator*(); // Also provides a uniform target for the iterator 'operator*'
// and 'operator()' methods
class iteratorProxy
{
iterator* iter_;
public:
//- Return proxy for assigning the referenced value //- Construct from pointer to iterator
inline iteratorProxy operator()(); inline iteratorProxy(iterator*);
inline iterator& operator++(); //- Assign value
inline iterator operator++(int); inline void operator=(const unsigned int val);
};
//- iterator set to the beginning of the PackedList //- Conversion operator
inline iterator begin(); inline operator unsigned int () const;
};
//- iterator set to beyond the end of the HashTable public:
inline iterator end();
// Constructors
//- Construct from base list and position index
inline iterator(const PackedList*, const label);
//- Assign value directly
inline void operator=(unsigned int);
//- Return value
inline unsigned int operator*() const;
//- Return value
inline unsigned int operator()() const;
//- Return proxy for assigning the referenced value
inline iteratorProxy operator*();
//- Return proxy for assigning the referenced value
inline iteratorProxy operator()();
inline iterator& operator++();
inline iterator operator++(int);
inline iterator& operator--();
inline iterator operator--(int);
};
//- iterator set to the beginning of the PackedList
inline iterator begin();
//- iterator set to beyond the end of the HashTable
inline iterator end();
}; };
@ -392,7 +412,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
# include "PackedListI.H" #include "PackedListI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -265,6 +265,56 @@ Foam::PackedList<nBits>::iterator::operator++(int)
} }
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator&
Foam::PackedList<nBits>::const_iterator::operator--()
{
if (!offset_)
{
offset_ = packing();
index_--;
}
offset_--;
return *this;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator--()
{
if (!this->offset_)
{
this->offset_ = packing();
this->index_--;
}
this->offset_--;
return *this;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::const_iterator::operator--(int)
{
const_iterator old = *this;
--*this;
return old;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::iterator::operator--(int)
{
iterator old = *this;
--*this;
return old;
}
template<int nBits> template<int nBits>
inline unsigned int inline unsigned int
Foam::PackedList<nBits>::const_iterator::operator*() const Foam::PackedList<nBits>::const_iterator::operator*() const
@ -298,9 +348,10 @@ Foam::PackedList<nBits>::iterator::operator()()
template<int nBits> template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::operator=(const unsigned int val) inline void
Foam::PackedList<nBits>::iterator::operator=(const unsigned int val)
{ {
return set(val); set(val);
} }
@ -331,12 +382,12 @@ unsigned int () const
template<int nBits> template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::iteratorProxy::operator= inline void Foam::PackedList<nBits>::iterator::iteratorProxy::operator=
( (
const unsigned int val const unsigned int val
) )
{ {
return iter_->set(val); iter_->set(val);
} }
@ -420,6 +471,7 @@ inline void Foam::PackedList<nBits>::resize
{ {
// fill value for complete chunks // fill value for complete chunks
unsigned int fill = val; unsigned int fill = val;
if (fill & ~max_value()) if (fill & ~max_value())
{ {
# ifdef DEBUGList # ifdef DEBUGList
@ -430,13 +482,15 @@ inline void Foam::PackedList<nBits>::resize
<< abort(FatalError); << abort(FatalError);
# endif # endif
// treat overflow as max_value // treat overflow as max_value, fill everything
fill = max_value(); fill = ~0;
} }
else
for (unsigned int i = 1; i < packing(); ++i)
{ {
fill |= (fill << nBits); for (unsigned int i = 1; i < packing(); ++i)
{
fill |= (fill << nBits);
}
} }
unsigned begIdx = size_ / packing(); unsigned begIdx = size_ / packing();
@ -446,11 +500,7 @@ inline void Foam::PackedList<nBits>::resize
// partial chunk, preserve existing value // partial chunk, preserve existing value
if (begOff) if (begOff)
{ {
unsigned int maskOld = max_value(); unsigned int maskOld = (0x1 << (nBits * begOff)) - 1;
for (unsigned int i = 1; i < begOff; ++i)
{
maskOld |= (maskOld << nBits);
}
StorageList::operator[](begIdx) &= maskOld; StorageList::operator[](begIdx) &= maskOld;
StorageList::operator[](begIdx) |= ~maskOld & fill; StorageList::operator[](begIdx) |= ~maskOld & fill;
@ -551,6 +601,14 @@ inline void Foam::PackedList<nBits>::shrink()
} }
} }
template<int nBits>
inline Foam::List<unsigned int>&
Foam::PackedList<nBits>::storage()
{
return static_cast<StorageList&>(*this);
}
template<int nBits> 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
@ -591,7 +649,14 @@ inline unsigned int Foam::PackedList<nBits>::get(const label i) const
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(); if (i < size_)
{
return const_iterator(this, i).get();
}
else
{
return 0;
}
} }
@ -662,7 +727,6 @@ Foam::PackedList<nBits>::operator[](const label i)
} }
// specialization for nBits=1 isn't worth the bother // 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)
@ -670,6 +734,7 @@ inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
if (val) if (val)
{ {
unsigned int fill = val; unsigned int fill = val;
if (fill & ~max_value()) if (fill & ~max_value())
{ {
# ifdef DEBUGList # ifdef DEBUGList
@ -681,12 +746,14 @@ inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
# endif # endif
// treat overflow as max_value // treat overflow as max_value
fill = max_value(); fill = ~0;
} }
else
for (unsigned int i = 1; i < packing(); ++i)
{ {
fill |= (fill << nBits); for (unsigned int i = 1; i < packing(); ++i)
{
fill |= (fill << nBits);
}
} }
StorageList::operator=(fill); StorageList::operator=(fill);