mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
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:
@ -28,112 +28,144 @@ Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "OSspecific.H"
|
||||
|
||||
#include "IOstreams.H"
|
||||
#include "IStringStream.H"
|
||||
#include "scalar.H"
|
||||
#include "vector.H"
|
||||
#include "ListOps.H"
|
||||
#include "List.H"
|
||||
#include "PackedBoolList.H"
|
||||
#include <bitset>
|
||||
|
||||
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:
|
||||
|
||||
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);
|
||||
list1.print(Info);
|
||||
|
||||
printPackedList(list1);
|
||||
|
||||
Info<< "\ntest assign uniform value\n";
|
||||
list1 = 2;
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
Info<< "\ntest resize with value (without reallocation)\n";
|
||||
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;
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
Info<< "\ntest assign bool\n";
|
||||
list1 = true;
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
Info<< "\ntest resize without value (with reallocation)\n";
|
||||
list1.resize(12);
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
Info<< "\ntest resize with value (with reallocation)\n";
|
||||
list1.resize(25, list1.max_value());
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
Info<< "\ntest resize smaller (should not touch allocation)\n";
|
||||
list1.resize(8);
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
Info<< "\ntest append() operation\n";
|
||||
list1.append(2);
|
||||
list1.append(3);
|
||||
list1.append(4);
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
Info<< "\ntest reserve() operation\n";
|
||||
list1.reserve(32);
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
Info<< "\ntest shrink() operation\n";
|
||||
list1.shrink();
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
list1.setSize(15);
|
||||
printPackedList(list1);
|
||||
Info<< "\ntest setCapacity() operation\n";
|
||||
list1.setCapacity(15);
|
||||
list1.print(Info);
|
||||
|
||||
list1.setSize(32);
|
||||
printPackedList(list1);
|
||||
Info<< "\ntest setCapacity() operation\n";
|
||||
list1.setCapacity(30);
|
||||
list1.print(Info);
|
||||
|
||||
// test assignment
|
||||
Info<< "\ntest operator[] assignment\n";
|
||||
list1[16] = 5;
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
// auto-vivify
|
||||
Info<< "\ntest operator[] assignment with auto-vivify\n";
|
||||
list1[36] = list1.max_value();
|
||||
printPackedList(list1);
|
||||
list1.print(Info);
|
||||
|
||||
list1.setSize(4);
|
||||
printPackedList(list1);
|
||||
Info<< "\ntest setCapacity smaller\n";
|
||||
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);
|
||||
list2.append(4);
|
||||
Info<< "source list:\n";
|
||||
list1.print(Info);
|
||||
Info<< "destination list:\n";
|
||||
list2.print(Info);
|
||||
|
||||
cout << "after copy + append\n";
|
||||
printPackedList(list1);
|
||||
printPackedList(list2);
|
||||
Info<< "\ntest pattern that fills all bits\n";
|
||||
PackedList<4> list3(8, 8);
|
||||
list3[list3.size()-2] = 0;
|
||||
list3[list3.size()-1] = list3.max_value();
|
||||
list3.print(Info);
|
||||
|
||||
Info<< "\n\nDone.\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ License
|
||||
template<int nBits>
|
||||
Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val)
|
||||
:
|
||||
List<unsigned int>(storageSize(size)),
|
||||
List<PackedStorage>(packedLength(size), 0u),
|
||||
size_(size)
|
||||
{
|
||||
operator=(val);
|
||||
@ -41,7 +41,7 @@ Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val)
|
||||
template<int nBits>
|
||||
Foam::PackedList<nBits>::PackedList(const UList<label>& lst)
|
||||
:
|
||||
List<unsigned int>(storageSize(lst.size()), 0),
|
||||
List<PackedStorage>(packedLength(lst.size()), 0u),
|
||||
size_(lst.size())
|
||||
{
|
||||
forAll(lst, i)
|
||||
@ -51,7 +51,6 @@ Foam::PackedList<nBits>::PackedList(const UList<label>& lst)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
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 * * * * * * * * * * * * * //
|
||||
|
||||
template<int nBits>
|
||||
void Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst)
|
||||
{
|
||||
setCapacity(lst.size());
|
||||
List<unsigned int>::operator=(lst);
|
||||
List<PackedStorage>::operator=(lst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ SeeAlso
|
||||
|
||||
ToDo
|
||||
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
|
||||
PackedListI.H
|
||||
@ -52,7 +52,6 @@ SourceFiles
|
||||
#define PackedList_H
|
||||
|
||||
#include "labelList.H"
|
||||
#include "List.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -72,84 +71,6 @@ template<int nBits> class 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
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -159,6 +80,8 @@ class PackedList
|
||||
:
|
||||
private List<unsigned int>
|
||||
{
|
||||
typedef unsigned int PackedStorage;
|
||||
|
||||
// Private data
|
||||
|
||||
//- Number of nBits entries
|
||||
@ -166,16 +89,10 @@ class PackedList
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Calculate underlying list size
|
||||
inline static label storageSize(const label);
|
||||
//- Calculate the list length when packed
|
||||
inline static label packedLength(const label);
|
||||
|
||||
//- Calculate element index and offset (start) bit within storage
|
||||
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).
|
||||
//- Check index I is within valid range [ 0 .. max_value() ]
|
||||
inline void checkIndex(const label) const;
|
||||
|
||||
public:
|
||||
@ -184,23 +101,18 @@ public:
|
||||
|
||||
//- The max. number of bits that can be templated.
|
||||
// Might someday be useful for a template assert.
|
||||
inline static unsigned int max_bits()
|
||||
{
|
||||
return PackedBitRef<nBits>::max_bits();
|
||||
}
|
||||
inline static unsigned int 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
|
||||
inline static unsigned int max_value()
|
||||
{
|
||||
return PackedBitRef<nBits>::max_value();
|
||||
}
|
||||
inline static unsigned int max_value();
|
||||
|
||||
//- The number of entries per storage entry
|
||||
inline static unsigned int packing()
|
||||
{
|
||||
return PackedBitRef<nBits>::packing();
|
||||
}
|
||||
//- The number of entries per packed storage element
|
||||
inline static unsigned int packing();
|
||||
|
||||
// Forward declaration of iterator
|
||||
class iterator;
|
||||
friend class iterator;
|
||||
|
||||
|
||||
// Constructors
|
||||
@ -208,7 +120,7 @@ public:
|
||||
//- Null constructor
|
||||
inline PackedList();
|
||||
|
||||
//- Construct with given size. Note: initializes list to 0.
|
||||
//- Construct with given size, initializes list to 0.
|
||||
inline PackedList(const label size);
|
||||
|
||||
//- Construct with given size and value for all elements.
|
||||
@ -233,38 +145,41 @@ public:
|
||||
//- The number of elements that can be stored before resizing
|
||||
inline label capacity() const;
|
||||
|
||||
//- Number of packed elements.
|
||||
//- Number of entries.
|
||||
inline label size() const;
|
||||
|
||||
//- Return true if the list is empty (i.e., if size() == 0).
|
||||
inline bool empty() const;
|
||||
|
||||
//- Get value at index I.
|
||||
// Does not auto-vivifies elements.
|
||||
inline unsigned int get(const label i) const;
|
||||
// Does not auto-vivifies entries.
|
||||
inline unsigned int get(const label) const;
|
||||
|
||||
//- Set value at index I. Return true if value changed.
|
||||
// Does not auto-vivifies elements.
|
||||
inline bool set(const label i, const unsigned int val);
|
||||
// Does not auto-vivifies entries.
|
||||
inline bool set(const label, const unsigned int val);
|
||||
|
||||
//- Underlying storage
|
||||
//- Return the underlying packed storage
|
||||
inline const List<unsigned int>& storage() const;
|
||||
|
||||
//- Return as labelList
|
||||
//- Return the values as a labelList
|
||||
labelList values() const;
|
||||
|
||||
//- Print values and information
|
||||
Ostream& print(Ostream&) const;
|
||||
|
||||
// Edit
|
||||
|
||||
//- Alter the size of the underlying storage.
|
||||
// The addressed size will be truncated if needed to fit, but will
|
||||
// remain otherwise untouched.
|
||||
// Use this or reserve() in combination with append().
|
||||
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);
|
||||
|
||||
//- Reset size of List, optionally specify a value for new elements.
|
||||
//- Alias for resize()
|
||||
inline void setSize(const label, const unsigned int& val = 0);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
@ -272,8 +187,8 @@ public:
|
||||
// Optionally provide an initialization value for new elements.
|
||||
inline void reserve(const label, const unsigned int& val = 0);
|
||||
|
||||
//- Clear the list, i.e. set size to zero.
|
||||
//- Does not adjust the underlying storage
|
||||
//- Clear the list, i.e. set addressable size to zero.
|
||||
// Does not adjust the underlying storage
|
||||
inline void clear();
|
||||
|
||||
//- Clear the list and delete storage.
|
||||
@ -282,7 +197,7 @@ public:
|
||||
//- Shrink the allocated space to what is used.
|
||||
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.
|
||||
inline void transfer(PackedList<nBits>&);
|
||||
|
||||
@ -291,17 +206,17 @@ public:
|
||||
|
||||
// Member operators
|
||||
|
||||
//- Append a value at the end of the list. Return true if value changed.
|
||||
inline bool append(const unsigned int val);
|
||||
//- Append a value at the end of the list
|
||||
inline void append(const unsigned int val);
|
||||
|
||||
//- Get value at index I
|
||||
// Does not auto-vivifies elements.
|
||||
inline unsigned int operator[](const label i) const;
|
||||
// Auto-vivifies any new values to zero.
|
||||
inline unsigned int operator[](const label) const;
|
||||
|
||||
//- Set value at index I.
|
||||
// Returns proxy to perform the actual operation.
|
||||
// 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.
|
||||
// Does set on all elements.
|
||||
@ -318,6 +233,71 @@ public:
|
||||
// // Write PackedList to Ostream.
|
||||
// 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();
|
||||
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -25,71 +25,38 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef PackedListI_H
|
||||
#define PackedListI_H
|
||||
|
||||
#include "IOstreams.H"
|
||||
#include "error.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
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>
|
||||
inline unsigned int Foam::PackedBitRef<nBits>::max_value()
|
||||
inline unsigned int Foam::PackedList<nBits>::max_value()
|
||||
{
|
||||
return ((1u << nBits) - 1);
|
||||
}
|
||||
|
||||
|
||||
template<int nBits>
|
||||
inline unsigned int Foam::PackedBitRef<nBits>::packing()
|
||||
inline unsigned int Foam::PackedList<nBits>::packing()
|
||||
{
|
||||
return sizeof(unsigned int)*8 / nBits;
|
||||
}
|
||||
|
||||
|
||||
// Calculate underlying list size
|
||||
template<int nBits>
|
||||
inline Foam::label Foam::PackedList<nBits>::storageSize(const label sz)
|
||||
{
|
||||
return (sz + packing() - 1) / packing();
|
||||
return sizeof(PackedStorage)*8 / nBits;
|
||||
}
|
||||
|
||||
|
||||
template<int nBits>
|
||||
inline Foam::label Foam::PackedList<nBits>::location
|
||||
(
|
||||
const label i,
|
||||
label& offset
|
||||
)
|
||||
inline Foam::label Foam::PackedList<nBits>::packedLength(const label nElem)
|
||||
{
|
||||
// the offset is the start bit within the storage element
|
||||
offset = nBits * (i % packing());
|
||||
return i / packing();
|
||||
return (nElem + packing() - 1) / 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>
|
||||
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 * * * * * * * * * * * * * * //
|
||||
|
||||
// Null constructor
|
||||
template<int nBits>
|
||||
inline Foam::PackedList<nBits>::PackedList()
|
||||
:
|
||||
List<unsigned int>(),
|
||||
List<PackedStorage>(),
|
||||
size_(0)
|
||||
{}
|
||||
|
||||
|
||||
// Construct with given size.
|
||||
template<int nBits>
|
||||
inline Foam::PackedList<nBits>::PackedList(const label size)
|
||||
:
|
||||
List<unsigned int>(storageSize(size), 0u),
|
||||
List<PackedStorage>(packedLength(size), 0u),
|
||||
size_(size)
|
||||
{}
|
||||
|
||||
@ -131,7 +96,7 @@ inline Foam::PackedList<nBits>::PackedList(const label size)
|
||||
template<int nBits>
|
||||
inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst)
|
||||
:
|
||||
List<unsigned int>(lst),
|
||||
List<PackedStorage>(lst),
|
||||
size_(lst.size())
|
||||
{}
|
||||
|
||||
@ -143,14 +108,161 @@ inline Foam::PackedList<nBits>::PackedList(const Xfer<PackedList<nBits> >& lst)
|
||||
}
|
||||
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * 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 * * * * * * * * * * * * * //
|
||||
|
||||
template<int nBits>
|
||||
@ -170,12 +282,12 @@ inline bool Foam::PackedList<nBits>::empty() const
|
||||
template<int nBits>
|
||||
inline void Foam::PackedList<nBits>::resize
|
||||
(
|
||||
const label newSize,
|
||||
const label nElem,
|
||||
const unsigned int& val
|
||||
)
|
||||
{
|
||||
reserve(newSize, val);
|
||||
size_ = newSize;
|
||||
reserve(nElem, val);
|
||||
size_ = nElem;
|
||||
}
|
||||
|
||||
|
||||
@ -194,21 +306,35 @@ inline void Foam::PackedList<nBits>::setSize
|
||||
template<int nBits>
|
||||
inline Foam::label Foam::PackedList<nBits>::capacity() const
|
||||
{
|
||||
return packing() * List<unsigned int>::size();
|
||||
return packing() * List<PackedStorage>::size();
|
||||
}
|
||||
|
||||
|
||||
template<int nBits>
|
||||
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
|
||||
)
|
||||
{
|
||||
label rawSize = storageSize(nElem);
|
||||
label len = packedLength(nElem);
|
||||
|
||||
// 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++)
|
||||
{
|
||||
set(i, val);
|
||||
@ -245,7 +371,7 @@ inline void Foam::PackedList<nBits>::clear()
|
||||
template<int nBits>
|
||||
inline void Foam::PackedList<nBits>::clearStorage()
|
||||
{
|
||||
List<unsigned int>::clear();
|
||||
List<PackedStorage>::clear();
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
@ -253,86 +379,20 @@ inline void Foam::PackedList<nBits>::clearStorage()
|
||||
template<int nBits>
|
||||
inline void Foam::PackedList<nBits>::shrink()
|
||||
{
|
||||
label rawSize = storageSize(size_);
|
||||
label len = packedLength(size_);
|
||||
|
||||
// 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>
|
||||
inline unsigned int Foam::PackedList<nBits>::get(const label i) const
|
||||
inline const Foam::List<unsigned int>&
|
||||
Foam::PackedList<nBits>::storage() const
|
||||
{
|
||||
# ifdef DEBUGList
|
||||
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);
|
||||
return static_cast<const List<PackedStorage>&>(*this);
|
||||
}
|
||||
|
||||
|
||||
@ -342,11 +402,10 @@ inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst)
|
||||
size_ = lst.size_;
|
||||
lst.size_ = 0;
|
||||
|
||||
List<unsigned int>::transfer(lst);
|
||||
List<PackedStorage>::transfer(lst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int nBits>
|
||||
inline Foam::Xfer<Foam::PackedList<nBits> >
|
||||
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>
|
||||
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)
|
||||
{
|
||||
if (i >= size_)
|
||||
@ -365,45 +484,25 @@ Foam::PackedList<nBits>::operator[](const label i)
|
||||
setSize(i + 1);
|
||||
}
|
||||
|
||||
label startBit;
|
||||
unsigned int& elem = List<unsigned int>::operator[]
|
||||
(
|
||||
location(i, startBit)
|
||||
);
|
||||
|
||||
return ::Foam::PackedBitRef<nBits>
|
||||
(
|
||||
// *this,
|
||||
elem,
|
||||
startBit
|
||||
);
|
||||
return iterator(*this, i);
|
||||
}
|
||||
|
||||
|
||||
// Set all to val
|
||||
template<int nBits>
|
||||
inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
|
||||
{
|
||||
# ifdef DEBUGList
|
||||
checkValue(val);
|
||||
# endif
|
||||
|
||||
if (val)
|
||||
{
|
||||
forAll(*this, i)
|
||||
forAll(*this, elemI)
|
||||
{
|
||||
set(i, val);
|
||||
set(elemI, val);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<unsigned int>::operator=(val);
|
||||
List<PackedStorage>::operator=(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
Reference in New Issue
Block a user