PackedList improvements

- dropped auto-vivification for now (performance issue), but reworked to
  allow easy reinstatement
- derived both iterator and const_iterator from iteratorBase and use
  iteratorBase as our proxy for non-const access to the list elements.
  This allows properly chaining assignments:
     list[1] = list[2];
     list[1] = list[2] = 10;
- assigning iterators from iteratorBase or other iterators works:
     iterator iter = list[20];
- made template parameter nBits=1 the default
This commit is contained in:
Mark Olesen
2009-01-29 14:03:53 +01:00
parent 69f8c3b3a1
commit 4e56643efe
6 changed files with 562 additions and 350 deletions

View File

@ -52,25 +52,29 @@ int main(int argc, char *argv[])
list1 = -1; list1 = -1;
list1.print(Info); list1.print(Info);
Info<< "\ntest assign between references - does not work as expected\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";
list1[4] = list1[2] = 1;
list1.print(Info);
{ {
const PackedList<3>& constLst = list1; const PackedList<3>& constLst = list1;
Info<< "\ntest operator[] const with out-of-range index\n"; Info<< "\ntest operator[] const with out-of-range index\n";
constLst.print(Info); constLst.print(Info);
if (!constLst[20]) if (!constLst[20])
{ {
Info<< "[20] is false, as expected\n"; Info<< "[20] is false (expected) list size should be unchanged (const)\n";
} }
constLst.print(Info); constLst.print(Info);
Info<< "\ntest operator[] non-const with out-of-range index\n"; Info<< "\ntest operator[] non-const with out-of-range index\n";
if (!list1[20]) if (!list1[20])
{ {
Info<< "[20] is false, as expected but list was resized!! (non-const)\n"; Info<< "[20] is false (expected) but list was resized?? (non-const)\n";
} }
list1.print(Info); list1.print(Info);
} }
@ -145,6 +149,10 @@ int main(int argc, char *argv[])
list1.setCapacity(24); list1.setCapacity(24);
list1.print(Info); list1.print(Info);
Info<< "\ntest resize much smaller\n";
list1.resize(150);
list1.print(Info);
Info<< "\ntest trim\n"; Info<< "\ntest trim\n";
list1.trim(); list1.trim();
list1.print(Info); list1.print(Info);
@ -159,13 +167,16 @@ int main(int argc, char *argv[])
Info<< "begin():"; Info<< "begin():";
iter.print(Info) << "\n"; iter.print(Info) << "\n";
Info<< "\ntest iterator operator=\n";
iter = 2;
Info<< "iterator:" << iter() << "\n"; Info<< "iterator:" << iter() << "\n";
iter = 5; iter() = 5;
iter.print(Info);
list1.print(Info); list1.print(Info);
iter = list1[31];
Info<< "iterator:" << iter() << "\n";
iter.print(Info);
Info<< "\ntest get() method\n"; Info<< "\ntest get() method\n";
Info<< "get(10):" << list1.get(10) << " and list[10]:" << list1[10] << "\n"; Info<< "get(10):" << list1.get(10) << " and list[10]:" << list1[10] << "\n";
list1.print(Info); list1.print(Info);
@ -173,25 +184,34 @@ 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";
{
Info<< "\ntest assignment of iterator\n";
list1.print(Info);
PackedList<3>::iterator cit = list1[25];
cit.print(Info);
list1.end().print(Info);
}
for for
( (
PackedList<3>::const_iterator cit = list1[30]; PackedList<3>::iterator cit = list1[5];
cit != list1.cend(); cit != list1.end();
++cit ++cit
) )
{ {
cit.print(Info); cit.print(Info);
} }
Info<< "\ntest operator[] auto-vivify\n"; // Info<< "\ntest operator[] auto-vivify\n";
const unsigned int val = list1[45]; // const unsigned int val = list1[45];
//
Info<< "list[45]:" << val << "\n"; // Info<< "list[45]:" << val << "\n";
list1[45] = list1.max_value(); // list1[45] = list1.max_value();
Info<< "list[45]:" << list1[45] << "\n"; // Info<< "list[45]:" << list1[45] << "\n";
list1[49] = list1.max_value(); // list1[49] = list1.max_value();
list1.print(Info); // list1.print(Info);
Info<< "\ntest copy constructor + append\n"; Info<< "\ntest copy constructor + append\n";

View File

@ -61,8 +61,8 @@ int main(int argc, char *argv[])
} }
cpuTime timer; cpuTime timer;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
packed.resize(40); packed.resize(40);
packed.shrink(); packed.shrink();
@ -76,7 +76,7 @@ int main(int argc, char *argv[])
// Count packed // Count packed
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(packed, i) forAll(packed, i)
{ {
@ -90,7 +90,7 @@ int main(int argc, char *argv[])
// Count packed // Count packed
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
sum += packed.count(); sum += packed.count();
} }
@ -101,7 +101,7 @@ int main(int argc, char *argv[])
// Dummy addition // Dummy addition
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(unpacked, i) forAll(unpacked, i)
{ {
@ -117,7 +117,7 @@ int main(int argc, char *argv[])
// Read stl // Read stl
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
for(unsigned int i = 0; i < stlVector.size(); i++) for(unsigned int i = 0; i < stlVector.size(); i++)
{ {
@ -130,7 +130,7 @@ int main(int argc, char *argv[])
// Read unpacked // Read unpacked
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(unpacked, i) forAll(unpacked, i)
{ {
@ -143,7 +143,7 @@ int main(int argc, char *argv[])
// Read packed // Read packed
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(packed, i) forAll(packed, i)
{ {
@ -157,7 +157,7 @@ int main(int argc, char *argv[])
// Read packed // Read packed
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(packed, i) forAll(packed, i)
{ {
@ -171,7 +171,7 @@ int main(int argc, char *argv[])
// Read via iterator // Read via iterator
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
for for
( (
@ -190,7 +190,7 @@ int main(int argc, char *argv[])
// Read via iterator // Read via iterator
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
for for
( (
@ -209,7 +209,7 @@ int main(int argc, char *argv[])
// Read empty hash // Read empty hash
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(unpacked, i) forAll(unpacked, i)
{ {
@ -223,7 +223,7 @@ int main(int argc, char *argv[])
// Read full hash // Read full hash
sum = 0; sum = 0;
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(unpacked, i) forAll(unpacked, i)
{ {
@ -240,7 +240,7 @@ int main(int argc, char *argv[])
// //
// Write stl // Write stl
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
for (unsigned int i = 0; i < stlVector.size(); i++) for (unsigned int i = 0; i < stlVector.size(); i++)
{ {
@ -250,7 +250,7 @@ int main(int argc, char *argv[])
Info<< "Writing stl:" << timer.cpuTimeIncrement() << " s" << endl; Info<< "Writing stl:" << timer.cpuTimeIncrement() << " s" << endl;
// Write unpacked // Write unpacked
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(unpacked, i) forAll(unpacked, i)
{ {
@ -261,7 +261,7 @@ int main(int argc, char *argv[])
// Write packed // Write packed
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(packed, i) forAll(packed, i)
{ {
@ -273,7 +273,7 @@ int main(int argc, char *argv[])
// Write packed // Write packed
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
forAll(packed, i) forAll(packed, i)
{ {
@ -283,25 +283,9 @@ int main(int argc, char *argv[])
Info<< "Writing packed using set:" << timer.cpuTimeIncrement() Info<< "Writing packed using set:" << timer.cpuTimeIncrement()
<< " s" << endl; << " s" << endl;
// Write packed
for (label iter = 0; iter < nIters; iter++)
{
for
(
PackedBoolList::iterator it = packed.begin();
it != packed.end();
++it
)
{
it = 1;
}
}
Info<< "Writing packed using iterator:" << timer.cpuTimeIncrement()
<< " s" << endl;
// Write packed // Write packed
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
for for
( (
@ -313,12 +297,12 @@ int main(int argc, char *argv[])
it() = 1; it() = 1;
} }
} }
Info<< "Writing packed using iteratorRef:" << timer.cpuTimeIncrement() Info<< "Writing packed using iterator:" << timer.cpuTimeIncrement()
<< " s" << endl; << " s" << endl;
// Write packed // Write packed
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
packed = 0; packed = 0;
} }
@ -327,7 +311,7 @@ int main(int argc, char *argv[])
// Write packed // Write packed
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
packed = 1; packed = 1;
} }
@ -338,7 +322,7 @@ int main(int argc, char *argv[])
PackedList<3> oddPacked(n, 3); PackedList<3> oddPacked(n, 3);
// Write packed // Write packed
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
packed = 0; packed = 0;
} }
@ -347,14 +331,14 @@ int main(int argc, char *argv[])
// Write packed // Write packed
for (label iter = 0; iter < nIters; iter++) for (label iter = 0; iter < nIters; ++iter)
{ {
packed = 1; packed = 1;
} }
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

@ -84,7 +84,7 @@ unsigned int Foam::PackedList<nBits>::count() const
if (size_) if (size_)
{ {
// mask value for complete chunks // mask value for complete chunks
unsigned int mask = (0x1 << (nBits * packing())) - 1; unsigned int mask = maskLower(packing());
unsigned int endIdx = size_ / packing(); unsigned int endIdx = size_ / packing();
unsigned int endOff = size_ % packing(); unsigned int endOff = size_ % packing();
@ -99,7 +99,7 @@ unsigned int Foam::PackedList<nBits>::count() const
// count bits in partial chunk // count bits in partial chunk
if (endOff) if (endOff)
{ {
mask = (0x1 << (nBits * endOff)) - 1; mask = maskLower(endOff);
register unsigned int bits = StorageList::operator[](endIdx) & mask; register unsigned int bits = StorageList::operator[](endIdx) & mask;
COUNT_PACKEDBITS(c, bits); COUNT_PACKEDBITS(c, bits);
@ -119,7 +119,7 @@ bool Foam::PackedList<nBits>::trim()
} }
// mask value for complete chunks // mask value for complete chunks
unsigned int mask = (0x1 << (nBits * packing())) - 1; unsigned int mask = maskLower(packing());
label currElem = packedLength(size_) - 1; label currElem = packedLength(size_) - 1;
unsigned int endOff = size_ % packing(); unsigned int endOff = size_ % packing();
@ -127,7 +127,7 @@ bool Foam::PackedList<nBits>::trim()
// clear trailing bits on final segment // clear trailing bits on final segment
if (endOff) if (endOff)
{ {
StorageList::operator[](currElem) &= ((0x1 << (nBits * endOff)) - 1); StorageList::operator[](currElem) &= maskLower(endOff);
} }
// test entire chunk // test entire chunk
@ -176,7 +176,7 @@ Foam::labelList Foam::PackedList<nBits>::values() const
template<int nBits> template<int nBits>
Foam::Ostream& Foam::PackedList<nBits>::const_iterator::print(Ostream& os) const Foam::Ostream& Foam::PackedList<nBits>::iteratorBase::print(Ostream& os) const
{ {
os << "iterator<" << nBits << "> [" os << "iterator<" << nBits << "> ["
<< (index_ * packing() + offset_) << "]" << (index_ * packing() + offset_) << "]"
@ -206,7 +206,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
<< "storage: " << packLen << "/" << StorageList::size() << "( "; << "storage: " << packLen << "/" << StorageList::size() << "( ";
// mask value for complete chunks // mask value for complete chunks
unsigned int mask = (0x1 << (nBits * packing())) - 1; unsigned int mask = maskLower(packing());
for (label i=0; i < packLen; i++) for (label i=0; i < packLen; i++)
{ {
@ -219,7 +219,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
if (endOff) if (endOff)
{ {
mask = (0x1 << (nBits * endOff)) - 1; mask = maskLower(endOff);
} }
else else
{ {
@ -227,7 +227,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
} }
} }
for (unsigned int testBit = 0x1 << max_bits(); testBit; testBit >>= 1) for (unsigned int testBit = (1 << max_bits()); testBit; testBit >>= 1)
{ {
if (testBit & mask) if (testBit & mask)
{ {

View File

@ -35,21 +35,32 @@ Description
The number of bits per item is specified by the template parameter nBits. The number of bits per item is specified by the template parameter nBits.
Note Note
The iterator '()' dereferencing operator returns a proxy class that handles In a const context, the '[]' operator simply returns the stored value,
assignment. However, the iterator itself can also handle assignment with out-of-range elements returned as zero.
directly, but does not return anything. In a non-const context, the '[]' operator returns an iteratorBase, which
Thus the following bit of code works as expected: may not have a valid reference for out-of-range elements.
The iteratorBase class handles the assignment of new values.
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
@endcode
Using get() or the '[]' operator are similarly fast. Looping and reading
with an iterator is approx. 15% slower, but can be more flexible.
Using the set() operator (and the '[]' operator) are marginally slower
(approx. 5%) than using an iterator, but the set() method has an
advantage that it also returns a bool if the value changed. This can be
useful for branching on changed values.
@code @code
blist[5] = 4; blist[5] = 4;
changed = blist.set(5, 8); changed = blist.set(5, 8);
changed = (blist[5] = 1); // ERROR - operator= is 'void' if (changed) ...
@endcode
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 @endcode
SeeAlso SeeAlso
@ -91,7 +102,7 @@ TemplateName(PackedList);
Class PackedList Declaration Class PackedList Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template <int nBits> template <int nBits=1>
class PackedList class PackedList
: :
private List<unsigned int> private List<unsigned int>
@ -127,9 +138,12 @@ public:
//- The number of entries per packed storage element //- The number of entries per packed storage element
inline static unsigned int packing(); inline static unsigned int packing();
// Forward declaration of iterator and const_iterator //- Masking for all bits below the offset
class iterator; inline static unsigned int maskLower(unsigned offset);
class const_iterator;
// Forward declaration of iteratorBase
class iteratorBase;
// Constructors // Constructors
@ -241,13 +255,13 @@ public:
inline unsigned int remove(); inline unsigned int remove();
//- Get value at index I //- Get value at index I
// Does not auto-vivify elements. // Does not 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.
// Auto-vivifies any new values to zero. // Does not auto-vivify entries.
inline iterator 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.
inline void operator=(const unsigned int val); inline void operator=(const unsigned int val);
@ -263,11 +277,12 @@ public:
// // 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 // Iterators and helpers
// 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 //- The iterator base for PackedList
// just inherited and used by iterator. // Note: data and functions are protected, to allow reuse by iterator
class const_iterator // and prevent most external usage.
class iteratorBase
{ {
friend class PackedList; friend class PackedList;
@ -275,57 +290,170 @@ public:
// Protected Data // Protected Data
//- Pointer to original list //- Pointer to original list
// 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 within storage
unsigned index_; unsigned index_;
//- Offset within storage element //- Offset within storage element
unsigned offset_; unsigned offset_;
// Protected Member Functions // Protected Member Functions
//- Get value as unsigned //- Get value as unsigned
inline unsigned int get() const; inline unsigned int get() const;
//- Set value, returning true if changed //- Set value, returning true if changed
// This is obviously used by iterator and not by const_iterator 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
//- 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
inline bool operator==(const iteratorBase&) const;
inline bool operator!=(const iteratorBase&) const;
//- Assign value, not position.
// This allows packed[0] = packed[3] for assigning values
inline unsigned int operator=(const iteratorBase&);
//- Assign value
inline unsigned int operator=(const unsigned int val);
//- Conversion operator
inline operator unsigned int () const;
//- Print value and information
Ostream& print(Ostream&) const;
};
//- The iterator class used for PackedList
class iterator
:
public iteratorBase
{
//- Should never violate const-ness!
void operator=(const const_iterator&);
public: public:
// Constructors // Constructors
//- Construct from base list and position index //- Construct null
inline const_iterator(const PackedList*, const label); inline iterator();
//- Construct from non-const iterator //- Construct from iterator base, eg iter(packedlist[i])
explicit inline const_iterator(const iterator&); inline iterator(const iteratorBase&);
//- Construct from base list and position index
inline iterator(const PackedList*, const label);
// Member Operators
//- Assign from iteratorBase, eg iter = packedlist[i]
inline iterator& operator=(const iteratorBase&);
//- Return value
inline unsigned int operator*() const;
//- Return value
inline unsigned int operator()() const;
//- Return iteratorBase for assigning values
inline iteratorBase& operator*();
//- Return iteratorBase for assigning values
inline iteratorBase& 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();
//- The const_iterator for PackedList
class const_iterator
:
public iteratorBase
{
public:
// Constructors
//- Construct null
inline const_iterator();
//- Construct from iterator base
inline const_iterator(const iteratorBase&);
//- Construct from base list and position index
inline const_iterator(const PackedList*, const label);
//- Construct from non-const iterator
inline const_iterator(const iterator&);
// Member operators // Member operators
inline bool operator==(const const_iterator&) const; //- Assign from iteratorBase or derived
inline bool operator!=(const const_iterator&) const; // eg, iter = packedlist[i] or iter = [non-const]list.begin()
inline const_iterator& operator=(const iteratorBase&);
//- Return referenced value directly //- Return referenced value directly
inline unsigned int operator*() const; inline unsigned int operator*() const;
//- Return referenced value directly //- Return referenced value directly
inline unsigned int operator()() const; inline unsigned int operator()() const;
inline const_iterator& operator++(); inline const_iterator& operator++();
inline const_iterator operator++(int); inline const_iterator operator++(int);
inline const_iterator& operator--(); inline const_iterator& operator--();
inline const_iterator operator--(int); inline const_iterator operator--(int);
//- Conversion operator
inline operator unsigned int () const;
//- Print value and information
Ostream& print(Ostream&) const;
}; };
@ -341,68 +469,6 @@ public:
//- const_iterator set to beyond the end of the PackedList //- const_iterator set to beyond the end of the PackedList
inline const_iterator end() const; inline const_iterator end() const;
//- The iterator class used for PackedList
class iterator
:
public const_iterator
{
friend class PackedList;
//- A 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_;
public:
//- Construct from pointer to iterator
inline iteratorProxy(iterator*);
//- Assign value
inline void operator=(const unsigned int val);
//- Conversion operator
inline operator unsigned int () const;
};
public:
// 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();
}; };

View File

@ -40,7 +40,7 @@ inline unsigned int Foam::PackedList<nBits>::max_bits()
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedList<nBits>::max_value() inline unsigned int Foam::PackedList<nBits>::max_value()
{ {
return (1u << nBits) - 1; return (1 << nBits) - 1;
} }
@ -51,6 +51,13 @@ inline unsigned int Foam::PackedList<nBits>::packing()
} }
template<int nBits>
inline unsigned int Foam::PackedList<nBits>::maskLower(unsigned offset)
{
return (1 << (nBits * offset)) - 1;
}
template<int nBits> template<int nBits>
inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem) inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem)
{ {
@ -119,8 +126,31 @@ Foam::PackedList<nBits>::clone() const
// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
// iteratorBase
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::const_iterator inline Foam::PackedList<nBits>::iteratorBase::iteratorBase()
:
list_(0),
index_(0),
offset_(0)
{}
template<int nBits>
inline Foam::PackedList<nBits>::iteratorBase::iteratorBase
(
const iteratorBase& iter
)
:
list_(iter.list_),
index_(iter.index_),
offset_(iter.offset_)
{}
template<int nBits>
inline Foam::PackedList<nBits>::iteratorBase::iteratorBase
( (
const PackedList<nBits>* lst, const PackedList<nBits>* lst,
const label i const label i
@ -133,50 +163,8 @@ inline Foam::PackedList<nBits>::const_iterator::const_iterator
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::iterator::iterator inline unsigned int
( Foam::PackedList<nBits>::iteratorBase::get() const
const PackedList<nBits>* lst,
const label i
)
:
const_iterator(lst, i)
{}
template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::const_iterator
(
const iterator& it
)
:
list_(it.list_),
index_(it.index_),
offset_(it.offset_)
{}
template<int nBits>
inline bool Foam::PackedList<nBits>::const_iterator::operator==
(
const const_iterator& iter
) const
{
return index_ == iter.index_ && offset_ == iter.offset_;
}
template<int nBits>
inline bool Foam::PackedList<nBits>::const_iterator::operator!=
(
const const_iterator& iter
) const
{
return !(operator==(iter));
}
template<int nBits>
inline unsigned int Foam::PackedList<nBits>::const_iterator::get() const
{ {
const unsigned int& stored = list_->StorageList::operator[](index_); const unsigned int& stored = list_->StorageList::operator[](index_);
return (stored >> (nBits * offset_)) & max_value(); return (stored >> (nBits * offset_)) & max_value();
@ -184,7 +172,8 @@ 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>::iteratorBase::set(const unsigned int val)
{ {
unsigned int& stored = list_->StorageList::operator[](index_); unsigned int& stored = list_->StorageList::operator[](index_);
const unsigned int prev = stored; const unsigned int prev = stored;
@ -195,9 +184,9 @@ inline bool Foam::PackedList<nBits>::const_iterator::set(const unsigned int val)
if (val & ~max_value()) if (val & ~max_value())
{ {
# ifdef DEBUGList # ifdef DEBUGList
FatalErrorIn("PackedList<T>::iterator::set(const unsigned int)") FatalErrorIn("PackedList<T>::iteratorBase::set(const unsigned int)")
<< "value " << label(val) << "value " << label(val)
<< " out-of-range 0 ... " << label(max_value()) w << " out-of-range 0 ... " << label(max_value())
<< " representable by " << nBits << " bits" << " representable by " << nBits << " bits"
<< abort(FatalError); << abort(FatalError);
# endif # endif
@ -216,8 +205,8 @@ inline bool Foam::PackedList<nBits>::const_iterator::set(const unsigned int val)
template<int nBits> template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator& inline void
Foam::PackedList<nBits>::const_iterator::operator++() Foam::PackedList<nBits>::iteratorBase::incr()
{ {
offset_++; offset_++;
if (offset_ >= packing()) if (offset_ >= packing())
@ -225,7 +214,219 @@ Foam::PackedList<nBits>::const_iterator::operator++()
offset_ = 0; offset_ = 0;
index_++; index_++;
} }
}
template<int nBits>
inline void
Foam::PackedList<nBits>::iteratorBase::decr()
{
if (!offset_)
{
offset_ = packing();
index_--;
}
offset_--;
}
template<int nBits>
inline void
Foam::PackedList<nBits>::iteratorBase::seek
(
const iteratorBase& iter
)
{
list_ = iter.list_;
index_ = iter.index_;
offset_ = iter.offset_;
this->validate();
}
template<int nBits>
inline bool
Foam::PackedList<nBits>::iteratorBase::valid() const
{
label elemI = offset_ + index_ * packing();
return (elemI < list_->size_);
}
template<int 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<int nBits>
inline bool Foam::PackedList<nBits>::iteratorBase::operator==
(
const iteratorBase& iter
) const
{
return this->index_ == iter.index_ && this->offset_ == iter.offset_;
}
template<int nBits>
inline bool Foam::PackedList<nBits>::iteratorBase::operator!=
(
const iteratorBase& iter
) const
{
return this->index_ != iter.index_ || this->offset_ != iter.offset_;
}
template<int nBits>
inline unsigned int
Foam::PackedList<nBits>::iteratorBase::operator=(const iteratorBase& iter)
{
const unsigned int val = iter.get();
this->set(val);
return val;
}
template<int 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_)
{
list_->resize(minsize);
}
#endif
this->set(val);
return val;
}
template<int 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_)
{
return 0;
}
#endif
return this->get();
}
// const_iterator, iterator
template<int nBits>
inline Foam::PackedList<nBits>::iterator::iterator()
:
iteratorBase()
{}
template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::const_iterator()
:
iteratorBase()
{}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::iterator
(
const iteratorBase& iter
)
:
iteratorBase(iter)
{
this->validate();
}
template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::const_iterator
(
const iteratorBase& iter
)
:
iteratorBase(iter)
{
this->validate();
}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::iterator
(
const PackedList<nBits>* lst,
const label i
)
:
iteratorBase(lst, i)
{}
template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::const_iterator
(
const PackedList<nBits>* lst,
const label i
)
:
iteratorBase(lst, i)
{}
template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::const_iterator
(
const iterator& iter
)
:
iteratorBase(static_cast<const iteratorBase&>(iter))
{}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator=(const iteratorBase& iter)
{
this->seek(iter);
return *this;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator&
Foam::PackedList<nBits>::const_iterator::operator=(const iteratorBase& iter)
{
this->seek(iter);
return *this; return *this;
} }
@ -234,24 +435,17 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::iterator& inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator++() Foam::PackedList<nBits>::iterator::operator++()
{ {
this->offset_++; this->incr();
if (this->offset_ >= packing())
{
this->offset_ = 0;
this->index_++;
}
return *this; return *this;
} }
template<int nBits> template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator inline typename Foam::PackedList<nBits>::const_iterator&
Foam::PackedList<nBits>::const_iterator::operator++(int) Foam::PackedList<nBits>::const_iterator::operator++()
{ {
const_iterator old = *this; this->incr();
++*this; return *this;
return old;
} }
@ -260,23 +454,18 @@ 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; this->incr();
return old; return old;
} }
template<int nBits> template<int 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++(int)
{ {
if (!offset_) const_iterator old = *this;
{ this->incr();
offset_ = packing(); return old;
index_--;
}
offset_--;
return *this;
} }
@ -284,24 +473,17 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::iterator& inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator--() Foam::PackedList<nBits>::iterator::operator--()
{ {
if (!this->offset_) this->decr();
{
this->offset_ = packing();
this->index_--;
}
this->offset_--;
return *this; return *this;
} }
template<int nBits> template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator inline typename Foam::PackedList<nBits>::const_iterator&
Foam::PackedList<nBits>::const_iterator::operator--(int) Foam::PackedList<nBits>::const_iterator::operator--()
{ {
const_iterator old = *this; this->decr();
--*this; return *this;
return old;
} }
@ -310,16 +492,42 @@ 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; this->decr();
return old; return old;
} }
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::const_iterator::operator--(int)
{
const_iterator old = *this;
this->decr();
return old;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iteratorBase&
Foam::PackedList<nBits>::iterator::operator*()
{
return static_cast<iteratorBase&>(*this);
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iteratorBase&
Foam::PackedList<nBits>::iterator::operator()()
{
return static_cast<iteratorBase&>(*this);
}
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
{ {
return get(); return this->get();
} }
@ -327,67 +535,7 @@ template<int nBits>
inline unsigned int inline unsigned int
Foam::PackedList<nBits>::const_iterator::operator()() const Foam::PackedList<nBits>::const_iterator::operator()() const
{ {
return get(); return this->get();
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator::iteratorProxy
Foam::PackedList<nBits>::iterator::operator*()
{
return iteratorProxy(this);
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator::iteratorProxy
Foam::PackedList<nBits>::iterator::operator()()
{
return iteratorProxy(this);
}
template<int nBits>
inline void
Foam::PackedList<nBits>::iterator::operator=(const unsigned int val)
{
set(val);
}
template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::operator
unsigned int () const
{
return get();
}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::iteratorProxy::iteratorProxy
(
PackedList<nBits>::iterator* it
)
:
iter_(it)
{}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::iteratorProxy::operator
unsigned int () const
{
return iter_->get();
}
template<int nBits>
inline void Foam::PackedList<nBits>::iterator::iteratorProxy::operator=
(
const unsigned int val
)
{
iter_->set(val);
} }
@ -427,7 +575,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, this->size()); return const_iterator(this, this->size());
} }
@ -435,7 +583,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, this->size()); return const_iterator(this, this->size());
} }
@ -500,7 +648,7 @@ inline void Foam::PackedList<nBits>::resize
// partial chunk, preserve existing value // partial chunk, preserve existing value
if (begOff) if (begOff)
{ {
unsigned int maskOld = (0x1 << (nBits * begOff)) - 1; unsigned int maskOld = maskLower(begOff);
StorageList::operator[](begIdx) &= maskOld; StorageList::operator[](begIdx) &= maskOld;
StorageList::operator[](begIdx) |= ~maskOld & fill; StorageList::operator[](begIdx) |= ~maskOld & fill;
@ -628,7 +776,7 @@ inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst)
template<int nBits> template<int nBits>
inline Foam::Xfer<Foam::PackedList<nBits> > inline Foam::Xfer< Foam::PackedList<nBits> >
Foam::PackedList<nBits>::xfer() Foam::PackedList<nBits>::xfer()
{ {
return xferMove(*this); return xferMove(*this);
@ -642,7 +790,7 @@ inline unsigned int Foam::PackedList<nBits>::get(const label i) const
checkIndex(i); checkIndex(i);
# endif # endif
return const_iterator(this, i).get(); return iteratorBase(this, i).get();
} }
@ -651,7 +799,7 @@ inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
{ {
if (i < size_) if (i < size_)
{ {
return const_iterator(this, i).get(); return iteratorBase(this, i).get();
} }
else else
{ {
@ -679,8 +827,7 @@ inline bool Foam::PackedList<nBits>::set
<< abort(FatalError); << abort(FatalError);
} }
# endif # endif
return iteratorBase(this, i).set(val);
return iterator(this, i).set(val);
} }
@ -691,7 +838,7 @@ inline void Foam::PackedList<nBits>::append(const unsigned int val)
reserve(elemI + 1); reserve(elemI + 1);
size_++; size_++;
iterator(this, elemI).set(val); iteratorBase(this, elemI).set(val);
} }
@ -707,7 +854,7 @@ inline unsigned int Foam::PackedList<nBits>::remove()
} }
label elemI = size_ - 1; label elemI = size_ - 1;
const unsigned int val = const_iterator(this, elemI).get(); const unsigned int val = iteratorBase(this, elemI).get();
resize(elemI); resize(elemI);
return val; return val;
@ -715,15 +862,10 @@ inline unsigned int Foam::PackedList<nBits>::remove()
template<int nBits> template<int nBits>
inline typename Foam::PackedList<nBits>::iterator inline typename Foam::PackedList<nBits>::iteratorBase
Foam::PackedList<nBits>::operator[](const label i) Foam::PackedList<nBits>::operator[](const label i)
{ {
if (i >= size_) return iteratorBase(this, i);
{
resize(i + 1);
}
return iterator(this, i);
} }

View File

@ -40,7 +40,7 @@ Description
namespace Foam namespace Foam
{ {
typedef PackedList<1> PackedBoolList; typedef PackedList<> PackedBoolList;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //