PackedList: encapsulate calculations in an iterator

- eliminated previous PackedBitRef class, the iterator does all of that and
  can also be used to (forward) traverse the list
- no const_iterator yet

- Note that PackedList is also a bit like DynamicList in terms of storage
  management and the append() method. Since the underlying storage in
  integer, any auto-vivified elements will also flood-fill the gaps with
  zero.
This commit is contained in:
Mark Olesen
2009-01-23 01:40:55 +01:00
parent 173607fd2d
commit cc4cd0a171
4 changed files with 527 additions and 349 deletions

View File

@ -28,112 +28,144 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "OSspecific.H"
#include "IOstreams.H" #include "IOstreams.H"
#include "IStringStream.H"
#include "scalar.H"
#include "vector.H"
#include "ListOps.H"
#include "List.H"
#include "PackedBoolList.H" #include "PackedBoolList.H"
#include <bitset>
using namespace Foam; using namespace Foam;
template <int nBits>
void printPackedList(const PackedList<nBits>& L)
{
const List<unsigned int>& stor = L.storage();
cout<< "PackedList<" << nBits << ">"
<< " max_bits:" << L.max_bits()
<< " max_value:" << L.max_value()
<< " packing:" << L.packing() << nl;
cout<< "values: " << L.size() << "/" << L.capacity() << " ( ";
forAll(L, i)
{
cout<< L[i] << ' ';
}
cout<< ")\n";
// using std:bitset for output works, but annoys valgrind
cout<< "storage: " << stor.size() << "( ";
forAll(stor, i)
{
cout<< std::bitset<32>(stor[i]) << ' ';
}
cout<< ")\n" << nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program: // Main program:
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
cout<< "PackedList::max_bits() = " << PackedList<0>::max_bits() << nl; bool changed;
Info<< "PackedList max_bits() = " << PackedList<0>::max_bits() << nl;
Info<< "\ntest allocation with value\n";
PackedList<3> list1(5,1); PackedList<3> list1(5,1);
list1.print(Info);
printPackedList(list1); Info<< "\ntest assign uniform value\n";
list1 = 2; list1 = 2;
printPackedList(list1); list1.print(Info);
Info<< "\ntest resize with value (without reallocation)\n";
list1.resize(6, 3); list1.resize(6, 3);
printPackedList(list1); list1.print(Info);
Info<< "\ntest set() function\n";
list1.set(1, 5);
list1.print(Info);
Info<< "\ntest assign bool\n";
list1 = false; list1 = false;
printPackedList(list1); list1.print(Info);
Info<< "\ntest assign bool\n";
list1 = true; list1 = true;
printPackedList(list1); list1.print(Info);
Info<< "\ntest resize without value (with reallocation)\n";
list1.resize(12); list1.resize(12);
printPackedList(list1); list1.print(Info);
Info<< "\ntest resize with value (with reallocation)\n";
list1.resize(25, list1.max_value()); list1.resize(25, list1.max_value());
printPackedList(list1); list1.print(Info);
Info<< "\ntest resize smaller (should not touch allocation)\n";
list1.resize(8); list1.resize(8);
printPackedList(list1); list1.print(Info);
Info<< "\ntest append() operation\n";
list1.append(2); list1.append(2);
list1.append(3); list1.append(3);
list1.append(4); list1.append(4);
printPackedList(list1); list1.print(Info);
Info<< "\ntest reserve() operation\n";
list1.reserve(32); list1.reserve(32);
printPackedList(list1); list1.print(Info);
Info<< "\ntest shrink() operation\n";
list1.shrink(); list1.shrink();
printPackedList(list1); list1.print(Info);
list1.setSize(15); Info<< "\ntest setCapacity() operation\n";
printPackedList(list1); list1.setCapacity(15);
list1.print(Info);
list1.setSize(32); Info<< "\ntest setCapacity() operation\n";
printPackedList(list1); list1.setCapacity(30);
list1.print(Info);
// test assignment Info<< "\ntest operator[] assignment\n";
list1[16] = 5; list1[16] = 5;
printPackedList(list1); list1.print(Info);
// auto-vivify Info<< "\ntest operator[] assignment with auto-vivify\n";
list1[36] = list1.max_value(); list1[36] = list1.max_value();
printPackedList(list1); list1.print(Info);
list1.setSize(4); Info<< "\ntest setCapacity smaller\n";
printPackedList(list1); list1.setCapacity(32);
list1.print(Info);
// add in some misc values
list1[31] = 1;
list1[32] = 2;
list1[33] = 3;
Info<< "\ntest iterator\n";
PackedList<3>::iterator iter = list1.begin();
Info<< "iterator:" << iter() << "\n";
iter.print(Info) << "\n";
Info<< "\ntest iterator operator=\n";
changed = (iter = 5);
Info<< "iterator:" << iter() << "\n";
Info<< "changed:" << changed << "\n";
changed = (iter = 5);
Info<< "changed:" << changed << "\n";
list1.print(Info);
Info<< "\ntest get() method\n";
Info<< "get(10):" << list1.get(10)
<< " and list[10]:" << unsigned(list1[10]) << "\n";
list1.print(Info);
Info<< "\ntest iterator indexing\n";
Info<< "end() ";
list1.end().print(Info) << "\n";
for (iter = list1[31]; iter != list1.end(); ++iter)
{
iter.print(Info);
}
Info<< "\ntest operator[] auto-vivify\n";
const unsigned int val = list1[45];
Info<< "list[45]:" << val << "\n";
list1.print(Info);
Info<< "\ntest copy constructor + append\n";
PackedList<3> list2(list1); PackedList<3> list2(list1);
list2.append(4); list2.append(4);
Info<< "source list:\n";
list1.print(Info);
Info<< "destination list:\n";
list2.print(Info);
cout << "after copy + append\n"; Info<< "\ntest pattern that fills all bits\n";
printPackedList(list1); PackedList<4> list3(8, 8);
printPackedList(list2); list3[list3.size()-2] = 0;
list3[list3.size()-1] = list3.max_value();
list3.print(Info);
Info<< "\n\nDone.\n";
return 0; return 0;
} }

View File

@ -31,7 +31,7 @@ License
template<int nBits> template<int nBits>
Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val) Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val)
: :
List<unsigned int>(storageSize(size)), List<PackedStorage>(packedLength(size), 0u),
size_(size) size_(size)
{ {
operator=(val); operator=(val);
@ -41,7 +41,7 @@ Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val)
template<int nBits> template<int nBits>
Foam::PackedList<nBits>::PackedList(const UList<label>& lst) Foam::PackedList<nBits>::PackedList(const UList<label>& lst)
: :
List<unsigned int>(storageSize(lst.size()), 0), List<PackedStorage>(packedLength(lst.size()), 0u),
size_(lst.size()) size_(lst.size())
{ {
forAll(lst, i) forAll(lst, i)
@ -51,7 +51,6 @@ Foam::PackedList<nBits>::PackedList(const UList<label>& lst)
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<int nBits> template<int nBits>
@ -67,13 +66,81 @@ Foam::labelList Foam::PackedList<nBits>::values() const
} }
template<int nBits>
Foam::Ostream& Foam::PackedList<nBits>::iterator::print(Ostream& os) const
{
os << "iterator<" << nBits << "> [" << position() << "]"
<< " elem:" << elem_ << " offset:" << offset_
<< " value:" << unsigned(*this)
<< nl;
return os;
}
template<int nBits>
Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
{
os << "PackedList<" << nBits << ">"
<< " max_value:" << max_value()
<< " packing:" << packing() << nl
<< "values: " << size() << "/" << capacity() << "( ";
forAll(*this, i)
{
os << get(i) << ' ';
}
os << ")\n"
<< "storage: " << storage().size() << "( ";
label count = size();
forAll(storage(), i)
{
const PackedStorage& rawBits = storage()[i];
// create mask for unaddressed bits
unsigned int addressed = 0;
for (unsigned packI = 0; count && packI < packing(); packI++, count--)
{
addressed <<= nBits;
addressed |= max_value();
}
for (unsigned int testBit = 0x1 << max_bits(); testBit; testBit >>= 1)
{
if (testBit & addressed)
{
if (rawBits & testBit)
{
os << '1';
}
else
{
os << '0';
}
}
else
{
os << '_';
}
}
cout << ' ';
}
os << ")\n";
return os;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<int nBits> template<int nBits>
void Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst) void Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst)
{ {
setCapacity(lst.size()); setCapacity(lst.size());
List<unsigned int>::operator=(lst); List<PackedStorage>::operator=(lst);
} }

View File

@ -40,7 +40,7 @@ SeeAlso
ToDo ToDo
Add checks for bad template parameters (ie, nBits=0, nBits too large). Add checks for bad template parameters (ie, nBits=0, nBits too large).
Could make PackedBitRef an iterator and use for traversing as well. The missing const_iterator might eventually still be needed.
SourceFiles SourceFiles
PackedListI.H PackedListI.H
@ -52,7 +52,6 @@ SourceFiles
#define PackedList_H #define PackedList_H
#include "labelList.H" #include "labelList.H"
#include "List.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -72,84 +71,6 @@ template<int nBits> class PackedList;
TemplateName(PackedList); TemplateName(PackedList);
/*---------------------------------------------------------------------------*\
Class PackedBitRef Declaration
\*---------------------------------------------------------------------------*/
//- The PackedBitRef is used for PackedList
template <int nBits>
class PackedBitRef
{
private:
// private data
// const mutable List<unsigned int>& list_;
unsigned int& elem_;
const label startBit_;
public:
// Static Public Members
//- The max. number of bits that can be templated.
// Might someday be useful for a template assert.
inline static unsigned int max_bits();
//- The max. value for an entry, can also be used as the mask
// eg, ((1 << 2) - 1) yields 0b0011
inline static unsigned int max_value();
//- The number of entries per storage entry
inline static unsigned int packing();
// Constructors
inline PackedBitRef
(
// const List<unsigned int>& lst
const unsigned int& elem, label startBit)
:
// list_(lst),
elem_(const_cast<unsigned int&>(elem)),
startBit_(startBit)
{}
// Members
// Assign value
inline void operator=(const unsigned int val)
{
unsigned int shiftedMask = max_value() << startBit_;
unsigned int shiftedVal = (val & max_value()) << startBit_;
elem_ = (elem_ & ~shiftedMask) | shiftedVal;
}
// return value
inline unsigned int operator()() const
{
return ((elem_ >> startBit_) & max_value());
}
//- Conversion operator
inline operator unsigned int () const
{
return ((elem_ >> startBit_) & max_value());
}
//- Conversion operator
inline operator bool() const
{
return !!((elem_ >> startBit_) & max_value());
}
};
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class PackedList Declaration Class PackedList Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -159,6 +80,8 @@ class PackedList
: :
private List<unsigned int> private List<unsigned int>
{ {
typedef unsigned int PackedStorage;
// Private data // Private data
//- Number of nBits entries //- Number of nBits entries
@ -166,16 +89,10 @@ class PackedList
// Private Member Functions // Private Member Functions
//- Calculate underlying list size //- Calculate the list length when packed
inline static label storageSize(const label); inline static label packedLength(const label);
//- Calculate element index and offset (start) bit within storage //- Check index I is within valid range [ 0 .. max_value() ]
inline static label location(const label, label& offset);
//- Check if value is representable in nBits
inline static void checkValue(const unsigned int);
//- Check index i is within valid range (0 ... size-1).
inline void checkIndex(const label) const; inline void checkIndex(const label) const;
public: public:
@ -184,23 +101,18 @@ public:
//- The max. number of bits that can be templated. //- The max. number of bits that can be templated.
// Might someday be useful for a template assert. // Might someday be useful for a template assert.
inline static unsigned int max_bits() inline static unsigned int max_bits();
{
return PackedBitRef<nBits>::max_bits();
}
//- The max. value for an entry, can also be used as the mask //- The max. value for an entry, which simultaneously the bit-mask
// eg, ((1 << 2) - 1) yields 0b0011 // eg, ((1 << 2) - 1) yields 0b0011
inline static unsigned int max_value() inline static unsigned int max_value();
{
return PackedBitRef<nBits>::max_value();
}
//- The number of entries per storage entry //- The number of entries per packed storage element
inline static unsigned int packing() inline static unsigned int packing();
{
return PackedBitRef<nBits>::packing(); // Forward declaration of iterator
} class iterator;
friend class iterator;
// Constructors // Constructors
@ -208,7 +120,7 @@ public:
//- Null constructor //- Null constructor
inline PackedList(); inline PackedList();
//- Construct with given size. Note: initializes list to 0. //- Construct with given size, initializes list to 0.
inline PackedList(const label size); inline PackedList(const label size);
//- Construct with given size and value for all elements. //- Construct with given size and value for all elements.
@ -233,38 +145,41 @@ public:
//- The number of elements that can be stored before resizing //- The number of elements that can be stored before resizing
inline label capacity() const; inline label capacity() const;
//- Number of packed elements. //- 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., if size() == 0).
inline bool empty() const; inline bool empty() const;
//- Get value at index I. //- Get value at index I.
// Does not auto-vivifies elements. // Does not auto-vivifies entries.
inline unsigned int get(const label i) 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-vivifies elements. // Does not auto-vivifies entries.
inline bool set(const label i, const unsigned int val); inline bool set(const label, const unsigned int val);
//- Underlying storage //- Return the underlying packed storage
inline const List<unsigned int>& storage() const; inline const List<unsigned int>& storage() const;
//- Return as labelList //- Return the values as a labelList
labelList values() const; labelList values() const;
//- Print values and information
Ostream& print(Ostream&) const;
// Edit // Edit
//- 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.
// Use this or reserve() in combination with append().
inline void setCapacity(const label); inline void setCapacity(const label);
//- Reset size of List, optionally specify a value for new elements. //- Reset addressable list size, does not shrink the allocated size.
// Optionally specify a value for new elements.
inline void resize(const label, const unsigned int& val = 0); inline void resize(const label, const unsigned int& val = 0);
//- Reset size of List, optionally specify a value for new elements. //- Alias for resize()
inline void setSize(const label, const unsigned int& val = 0); inline void setSize(const label, const unsigned int& val = 0);
//- Reserve allocation space for at least this size. //- Reserve allocation space for at least this size.
@ -272,8 +187,8 @@ public:
// Optionally provide an initialization value for new elements. // Optionally provide an initialization value for new elements.
inline void reserve(const label, const unsigned int& val = 0); inline void reserve(const label, const unsigned int& val = 0);
//- Clear the list, i.e. set size to zero. //- Clear the list, i.e. set addressable size to zero.
//- Does not adjust the underlying storage // Does not adjust the underlying storage
inline void clear(); inline void clear();
//- Clear the list and delete storage. //- Clear the list and delete storage.
@ -282,7 +197,7 @@ public:
//- Shrink the allocated space to what is used. //- Shrink the allocated space to what is used.
inline void shrink(); inline void shrink();
//- Transfer the contents of the argument List into this List //- Transfer the contents of the argument list into this list
// and annull the argument list. // and annull the argument list.
inline void transfer(PackedList<nBits>&); inline void transfer(PackedList<nBits>&);
@ -291,17 +206,17 @@ public:
// Member operators // Member operators
//- Append a value at the end of the list. Return true if value changed. //- Append a value at the end of the list
inline bool append(const unsigned int val); inline void append(const unsigned int val);
//- Get value at index I //- Get value at index I
// Does not auto-vivifies elements. // Auto-vivifies any new values to zero.
inline unsigned int operator[](const label i) const; inline unsigned int operator[](const label) const;
//- Set value at index I. //- Set value at index I.
// Returns proxy to perform the actual operation. // Returns proxy to perform the actual operation.
// Auto-vivifies any new values to zero. // Auto-vivifies any new values to zero.
inline ::Foam::PackedBitRef<nBits> operator[](const label i); inline iterator operator[](const label);
//- Assignment of all entries to the given value. //- Assignment of all entries to the given value.
// Does set on all elements. // Does set on all elements.
@ -318,6 +233,71 @@ 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 iterator-like class used for PackedList
class iterator
{
friend class PackedList;
// Private Data
//- Reference to original list
PackedList& list_;
//- Element index within storage
unsigned elem_;
//- Offset within storage element
unsigned offset_;
//- Return the raw storage element
inline PackedStorage& chunk() const;
//- Return the position in the PackedList
inline label position() const;
public:
// Constructors
//- Construct from base list and position index
inline iterator(const PackedList&, const label i);
// Members
//- Assign value, returns true if the value changed
inline bool operator=(const unsigned int val);
//- Conversion operator
inline operator unsigned int () const;
//- Conversion operator
inline operator bool() const;
// Member operators
inline void operator=(const iterator&);
inline bool operator==(const iterator&) const;
inline bool operator!=(const iterator&) const;
//- Return referenced value
inline unsigned int operator()() const;
inline iterator& operator++();
inline iterator operator++(int);
//- Print value and information
Ostream& print(Ostream&) const;
};
//- iterator set to the begining of the PackedList
inline iterator begin();
//- iterator set to beyond the end of the HashTable
inline iterator end();
}; };
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -25,71 +25,38 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef PackedListI_H #include "error.H"
#define PackedListI_H
#include "IOstreams.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedBitRef<nBits>::max_bits() inline unsigned int Foam::PackedList<nBits>::max_bits()
{ {
return sizeof(unsigned int)*8 - 1; return sizeof(PackedStorage)*8 - 1;
} }
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedBitRef<nBits>::max_value() inline unsigned int Foam::PackedList<nBits>::max_value()
{ {
return ((1u << nBits) - 1); return ((1u << nBits) - 1);
} }
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedBitRef<nBits>::packing() inline unsigned int Foam::PackedList<nBits>::packing()
{ {
return sizeof(unsigned int)*8 / nBits; return sizeof(PackedStorage)*8 / nBits;
}
// Calculate underlying list size
template<int nBits>
inline Foam::label Foam::PackedList<nBits>::storageSize(const label sz)
{
return (sz + packing() - 1) / packing();
} }
template<int nBits> template<int nBits>
inline Foam::label Foam::PackedList<nBits>::location inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem)
(
const label i,
label& offset
)
{ {
// the offset is the start bit within the storage element return (nElem + packing() - 1) / packing();
offset = nBits * (i % packing());
return i / packing();
} }
// Check value is representable in nBits
template<int nBits>
inline void Foam::PackedList<nBits>::checkValue(const unsigned int val)
{
if (val > max_value())
{
FatalErrorIn("PackedList<T>::checkValue(const unsigned int)")
<< "value " << label(val) << " out of range 0 ... "
<< label(max_value())
<< " representable by " << nBits << " bits"
<< abort(FatalError);
}
}
// Check index i is within valid range (0 ... size-1).
template<int nBits> template<int nBits>
inline void Foam::PackedList<nBits>::checkIndex(const label i) const inline void Foam::PackedList<nBits>::checkIndex(const label i) const
{ {
@ -110,20 +77,18 @@ inline void Foam::PackedList<nBits>::checkIndex(const label i) const
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Null constructor
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::PackedList() inline Foam::PackedList<nBits>::PackedList()
: :
List<unsigned int>(), List<PackedStorage>(),
size_(0) size_(0)
{} {}
// Construct with given size.
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::PackedList(const label size) inline Foam::PackedList<nBits>::PackedList(const label size)
: :
List<unsigned int>(storageSize(size), 0u), List<PackedStorage>(packedLength(size), 0u),
size_(size) size_(size)
{} {}
@ -131,7 +96,7 @@ inline Foam::PackedList<nBits>::PackedList(const label size)
template<int nBits> template<int nBits>
inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst) inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst)
: :
List<unsigned int>(lst), List<PackedStorage>(lst),
size_(lst.size()) size_(lst.size())
{} {}
@ -143,14 +108,161 @@ inline Foam::PackedList<nBits>::PackedList(const Xfer<PackedList<nBits> >& lst)
} }
template<int nBits> template<int nBits>
inline Foam::autoPtr<Foam::PackedList<nBits> > Foam::PackedList<nBits>::clone() const inline Foam::autoPtr<Foam::PackedList<nBits> >
Foam::PackedList<nBits>::clone() const
{ {
return autoPtr<PackedList<nBits> >(new PackedList<nBits>(*this)); return autoPtr<PackedList<nBits> >(new PackedList<nBits>(*this));
} }
// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
template<int nBits>
inline Foam::PackedList<nBits>::iterator::iterator
(
const PackedList<nBits>& lst,
const label i
)
:
list_(const_cast<PackedList<nBits>&>(lst)),
elem_(i / packing()),
offset_(i % packing())
{}
template<int nBits>
inline void Foam::PackedList<nBits>::iterator::operator=
(
const iterator& iter
)
{
elem_ = iter.elem_;
offset_ = iter.offset_;
}
template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::operator==
(
const iterator& iter
) const
{
return elem_ == iter.elem_ && offset_ == iter.offset_;
}
template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::operator!=
(
const iterator& iter
) const
{
return !(operator==(iter));
}
template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::operator=
(
const unsigned int val
)
{
const unsigned int startBit = nBits * offset_;
const unsigned int mask = max_value() << startBit;
unsigned int& stored = chunk();
const unsigned int old = stored;
stored &= ~mask;
stored |= (val << startBit) & mask;
return (old != stored);
}
template<int nBits>
inline Foam::label Foam::PackedList<nBits>::iterator::position() const
{
return (elem_ * packing() + offset_);
}
template<int nBits>
inline unsigned int& Foam::PackedList<nBits>::iterator::chunk() const
{
return list_.List<PackedStorage>::operator[](elem_);
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator++()
{
if (position() < list_.size())
{
offset_++;
if (offset_ >= packing())
{
elem_++;
offset_ = 0;
}
}
return *this;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::iterator::operator++(int)
{
iterator old = *this;
++*this;
return old;
}
template<int nBits>
inline unsigned int
Foam::PackedList<nBits>::iterator::operator()() const
{
return (chunk() >> (nBits * offset_)) & max_value();
}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::operator
unsigned int () const
{
return (chunk() >> (nBits * offset_)) & max_value();
}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::operator
bool() const
{
return !!(chunk() >> (nBits * offset_)) & max_value();
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::begin()
{
return iterator(*this, 0);
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::end()
{
return iterator(*this, size());
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<int nBits> template<int nBits>
@ -170,12 +282,12 @@ inline bool Foam::PackedList<nBits>::empty() const
template<int nBits> template<int nBits>
inline void Foam::PackedList<nBits>::resize inline void Foam::PackedList<nBits>::resize
( (
const label newSize, const label nElem,
const unsigned int& val const unsigned int& val
) )
{ {
reserve(newSize, val); reserve(nElem, val);
size_ = newSize; size_ = nElem;
} }
@ -194,21 +306,35 @@ inline void Foam::PackedList<nBits>::setSize
template<int nBits> template<int nBits>
inline Foam::label Foam::PackedList<nBits>::capacity() const inline Foam::label Foam::PackedList<nBits>::capacity() const
{ {
return packing() * List<unsigned int>::size(); return packing() * List<PackedStorage>::size();
} }
template<int nBits> template<int nBits>
inline void Foam::PackedList<nBits>::setCapacity(const label nElem) inline void Foam::PackedList<nBits>::setCapacity(const label nElem)
{ {
List<unsigned int>::setSize(storageSize(nElem), 0); List<PackedStorage>::setSize(packedLength(nElem), 0u);
for (label i = size_; i < nElem; i++) // truncates addressable section too
if (size_ > nElem)
{ {
set(i, 0); # ifdef DEBUGList
// clear old values (purely cosmetics for string output)
for (label i = nElem; i < size_; i++)
{
set(i, 0);
}
# endif
size_ = nElem;
}
else
{
// fill new elements
for (label i = size_; i < nElem; i++)
{
set(i, 0);
}
} }
size_ = nElem;
} }
@ -219,15 +345,15 @@ inline void Foam::PackedList<nBits>::reserve
const unsigned int& val const unsigned int& val
) )
{ {
label rawSize = storageSize(nElem); label len = packedLength(nElem);
// need more capacity? // need more capacity?
if (rawSize > List<unsigned int>::size()) if (len > List<PackedStorage>::size())
{ {
List<unsigned int>::setSize(rawSize, 0); List<PackedStorage>::setSize(len, 0);
} }
// fill new elements, don't rely on List::setSize // fill new elements
for (label i = size_; i < nElem; i++) for (label i = size_; i < nElem; i++)
{ {
set(i, val); set(i, val);
@ -245,7 +371,7 @@ inline void Foam::PackedList<nBits>::clear()
template<int nBits> template<int nBits>
inline void Foam::PackedList<nBits>::clearStorage() inline void Foam::PackedList<nBits>::clearStorage()
{ {
List<unsigned int>::clear(); List<PackedStorage>::clear();
size_ = 0; size_ = 0;
} }
@ -253,86 +379,20 @@ inline void Foam::PackedList<nBits>::clearStorage()
template<int nBits> template<int nBits>
inline void Foam::PackedList<nBits>::shrink() inline void Foam::PackedList<nBits>::shrink()
{ {
label rawSize = storageSize(size_); label len = packedLength(size_);
// we have unused space? // we have unused space?
if (rawSize < List<unsigned int>::size()) if (len < List<PackedStorage>::size())
{ {
List<unsigned int>::setSize(rawSize); List<PackedStorage>::setSize(len);
} }
} }
// Get value at i
template<int nBits> template<int nBits>
inline unsigned int Foam::PackedList<nBits>::get(const label i) const inline const Foam::List<unsigned int>&
Foam::PackedList<nBits>::storage() const
{ {
# ifdef DEBUGList return static_cast<const List<PackedStorage>&>(*this);
checkIndex(i);
# endif
label startBit;
const unsigned int& elem = List<unsigned int>::operator[]
(
location(i, startBit)
);
// PackedBitRef<nBits> iter(*this, elem, startBit);
// return PackedBitRef<nBits>(*this, elem, startBit)();
return (elem >> startBit) & max_value();
}
template<int nBits>
inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
{
return get(i);
}
// Set value at i
template<int nBits>
inline bool Foam::PackedList<nBits>::set(const label i, const unsigned int val)
{
# ifdef DEBUGList
checkIndex(i);
checkValue(val);
# endif
label startBit;
unsigned int& elem = List<unsigned int>::operator[]
(
location(i, startBit)
);
unsigned int oldElem = elem;
unsigned int shiftedMask = max_value() << startBit;
unsigned int shiftedVal = (val & max_value()) << startBit;
elem = (elem & ~shiftedMask) | shiftedVal;
return elem != oldElem;
}
template<int nBits>
inline bool Foam::PackedList<nBits>::append(const unsigned int val)
{
label elemI = size_;
reserve(elemI + 1);
size_++;
return set(elemI, val);
}
template<int nBits>
inline const Foam::List<unsigned int>& Foam::PackedList<nBits>::storage() const
{
return static_cast<const List<unsigned int>&>(*this);
} }
@ -342,11 +402,10 @@ inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst)
size_ = lst.size_; size_ = lst.size_;
lst.size_ = 0; lst.size_ = 0;
List<unsigned int>::transfer(lst); List<PackedStorage>::transfer(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()
@ -355,9 +414,69 @@ Foam::PackedList<nBits>::xfer()
} }
template<int nBits>
inline unsigned int Foam::PackedList<nBits>::get(const label i) const
{
# ifdef DEBUGList
checkIndex(i);
# endif
return iterator(*this, i)();
}
template<int nBits> template<int nBits>
inline typename Foam::PackedBitRef<nBits> inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
{
if (i >= size_)
{
setSize(i + 1);
return 0;
}
else
{
return iterator(*this, i)();
}
}
template<int nBits>
inline bool Foam::PackedList<nBits>::set
(
const label i,
const unsigned int val
)
{
# ifdef DEBUGList
checkIndex(i);
if (val & ~max_value())
{
FatalErrorIn("PackedList<T>::set(const label, const unsigned int)")
<< "value " << label(val)
<< " out-of-range 0 ... " << label(max_value())
<< " representable by " << nBits << " bits"
<< abort(FatalError);
}
# endif
return (iterator(*this, i) = val);
}
template<int nBits>
inline void Foam::PackedList<nBits>::append(const unsigned int val)
{
label elemI = size_;
reserve(elemI + 1);
size_++;
iterator(*this, elemI) = val;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::operator[](const label i) Foam::PackedList<nBits>::operator[](const label i)
{ {
if (i >= size_) if (i >= size_)
@ -365,45 +484,25 @@ Foam::PackedList<nBits>::operator[](const label i)
setSize(i + 1); setSize(i + 1);
} }
label startBit; return iterator(*this, i);
unsigned int& elem = List<unsigned int>::operator[]
(
location(i, startBit)
);
return ::Foam::PackedBitRef<nBits>
(
// *this,
elem,
startBit
);
} }
// Set all to val
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)
{ {
# ifdef DEBUGList
checkValue(val);
# endif
if (val) if (val)
{ {
forAll(*this, i) forAll(*this, elemI)
{ {
set(i, val); set(elemI, val);
} }
} }
else else
{ {
List<unsigned int>::operator=(val); List<PackedStorage>::operator=(val);
} }
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* // // ************************************************************************* //