PackedList changes

- added Mattijs' speed tests
- optimized resize() and assignment operators to avoid set() method
- add const_iterator and re-did the proxy handling.

Reading/writing by looping across iterators is still somewhat slow, but
might be acceptable.
This commit is contained in:
Mark Olesen
2009-01-26 00:33:28 +01:00
parent 42c04b8505
commit 84ec272d23
7 changed files with 774 additions and 160 deletions

View File

@ -46,11 +46,11 @@ int main(int argc, char *argv[])
list1.print(Info);
Info<< "\ntest assign uniform value\n";
list1 = 2;
list1 = 4;
list1.print(Info);
Info<< "\ntest resize with value (without reallocation)\n";
list1.resize(6, 3);
list1.resize(8, list1.max_value());
list1.print(Info);
Info<< "\ntest set() function\n";
@ -96,7 +96,7 @@ int main(int argc, char *argv[])
list1.print(Info);
Info<< "\ntest setCapacity() operation\n";
list1.setCapacity(30);
list1.setCapacity(100);
list1.print(Info);
Info<< "\ntest operator[] assignment\n";
@ -108,7 +108,7 @@ int main(int argc, char *argv[])
list1.print(Info);
Info<< "\ntest setCapacity smaller\n";
list1.setCapacity(32);
list1.setCapacity(24);
list1.print(Info);
// add in some misc values
@ -118,7 +118,7 @@ int main(int argc, char *argv[])
Info<< "\ntest iterator\n";
PackedList<3>::iterator iter = list1.begin();
Info<< "iterator:" << iter() << "\n";
Info<< "begin():";
iter.print(Info) << "\n";
Info<< "\ntest iterator operator=\n";
@ -131,23 +131,29 @@ int main(int argc, char *argv[])
list1.print(Info);
Info<< "\ntest get() method\n";
Info<< "get(10):" << list1.get(10)
<< " and list[10]:" << unsigned(list1[10]) << "\n";
Info<< "get(10):" << list1.get(10) << " and list[10]:" << list1[10] << "\n";
list1.print(Info);
Info<< "\ntest iterator indexing\n";
Info<< "end() ";
list1.end().print(Info) << "\n";
Info<< "cend() ";
list1.cend().print(Info) << "\n";
for (iter = list1[31]; iter != list1.end(); ++iter)
for
(
PackedList<3>::const_iterator cit = list1[30];
cit != list1.cend();
++cit)
{
iter.print(Info);
cit.print(Info);
}
Info<< "\ntest operator[] auto-vivify\n";
const unsigned int val = list1[45];
Info<< "list[45]:" << val << "\n";
list1[45] = list1.max_value();
Info<< "list[45]:" << list1[45] << "\n";
list1[49] = list1.max_value();
list1.print(Info);
@ -161,8 +167,15 @@ int main(int argc, char *argv[])
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();
label pos = list3.size() - 1;
list3[pos--] = list3.max_value();
list3[pos--] = 0;
list3[pos--] = list3.max_value();
list3.print(Info);
Info<< "removed final value: " << list3.remove() << endl;
list3.print(Info);
Info<< "\n\nDone.\n";

View File

@ -0,0 +1,3 @@
PackedListTest2.C
EXE = $(FOAM_USER_APPBIN)/PackedListTest2

View File

@ -0,0 +1,337 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
Description
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "boolList.H"
#include "PackedBoolList.H"
#include "HashSet.H"
#include "cpuTime.H"
#include <vector>
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
const label n = 1000000;
const label nIters = 1000;
unsigned int sum = 0;
PackedBoolList packed(n, 1);
boolList unpacked(n, true);
std::vector<bool> stlVector(n, true);
labelHashSet emptyHash;
labelHashSet fullHash;
for(label i = 0; i < n; i++)
{
fullHash.insert(i);
}
cpuTime timer;
for (label iter = 0; iter < nIters; iter++)
{
packed.resize(40);
packed.shrink();
packed.resize(n, 1);
}
Info<< "resize/shrink/resize:" << timer.cpuTimeIncrement() << " s\n\n";
// Dummy addition
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
forAll(unpacked, i)
{
sum += i + 1;
}
}
Info<< "Dummy loop:" << timer.cpuTimeIncrement() << " s" << endl;
Info<< " sum " << sum << endl;
//
// Read
//
// Read stl
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
for(unsigned int i = 0; i < stlVector.size(); i++)
{
sum += stlVector[i];
}
}
Info<< "Reading stl:" << timer.cpuTimeIncrement() << " s" << endl;
Info<< " sum " << sum << endl;
// Read unpacked
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
forAll(unpacked, i)
{
sum += unpacked[i];
}
}
Info<< "Reading unpacked:" << timer.cpuTimeIncrement() << " s" << endl;
Info<< " sum " << sum << endl;
// Read packed
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
forAll(packed, i)
{
sum += packed.get(i);
}
}
Info<< "Reading packed using get:" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
// Read packed
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
forAll(packed, i)
{
sum += packed[i];
}
}
Info<< "Reading packed using reference:" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
// Read via iterator
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
for
(
PackedBoolList::iterator it = packed.begin();
it != packed.end();
++it
)
{
sum += it;
}
}
Info<< "Reading packed using iterator:" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
// Read via iterator
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
for
(
PackedBoolList::const_iterator cit = packed.cbegin();
cit != packed.cend();
++cit
)
{
sum += cit();
}
}
Info<< "Reading packed using const_iterator():" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
// Read empty hash
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
forAll(packed, i)
{
sum += emptyHash.found(i);
}
}
Info<< "Reading empty labelHashSet:" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
// Read full hash
sum = 0;
for (label iter = 0; iter < nIters; iter++)
{
forAll(packed, i)
{
sum += fullHash.found(i);
}
}
Info<< "Reading full labelHashSet:" << timer.cpuTimeIncrement()
<< " s" << endl;
Info<< " sum " << sum << endl;
//
// Write
//
// Write stl
for (label iter = 0; iter < nIters; iter++)
{
for (unsigned int i = 0; i < stlVector.size(); i++)
{
stlVector[i] = true;
}
}
Info<< "Writing stl:" << timer.cpuTimeIncrement() << " s" << endl;
// Write unpacked
for (label iter = 0; iter < nIters; iter++)
{
forAll(unpacked, i)
{
unpacked[i] = true;
}
}
Info<< "Writing unpacked:" << timer.cpuTimeIncrement() << " s" << endl;
// Write packed
for (label iter = 0; iter < nIters; iter++)
{
forAll(packed, i)
{
packed[i] = 1;
}
}
Info<< "Writing packed using reference:" << timer.cpuTimeIncrement()
<< " s" << endl;
// Write packed
for (label iter = 0; iter < nIters; iter++)
{
forAll(packed, i)
{
packed.set(i, 1);
}
}
Info<< "Writing packed using set:" << timer.cpuTimeIncrement()
<< " 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
for (label iter = 0; iter < nIters; iter++)
{
for
(
PackedBoolList::iterator it = packed.begin();
it != packed.end();
++it
)
{
it() = 1;
}
}
Info<< "Writing packed using iteratorRef:" << timer.cpuTimeIncrement()
<< " s" << endl;
// Write packed
for (label iter = 0; iter < nIters; iter++)
{
packed = 0;
}
Info<< "Writing packed uniform 0:" << timer.cpuTimeIncrement()
<< " s" << endl;
// Write packed
for (label iter = 0; iter < nIters; iter++)
{
packed = 1;
}
Info<< "Writing packed uniform 1:" << timer.cpuTimeIncrement()
<< " s" << endl;
PackedList<3> oddPacked(n, 3);
// Write packed
for (label iter = 0; iter < nIters; iter++)
{
packed = 0;
}
Info<< "Writing packed<3> uniform 0:" << timer.cpuTimeIncrement()
<< " s" << endl;
// Write packed
for (label iter = 0; iter < nIters; iter++)
{
packed = 1;
}
Info<< "Writing packed<3> uniform 1:" << timer.cpuTimeIncrement()
<< " s" << endl;
Info << "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -67,10 +67,11 @@ Foam::labelList Foam::PackedList<nBits>::values() const
template<int nBits>
Foam::Ostream& Foam::PackedList<nBits>::iterator::print(Ostream& os) const
Foam::Ostream& Foam::PackedList<nBits>::const_iterator::print(Ostream& os) const
{
os << "iterator<" << nBits << "> [" << position() << "]"
<< " elem:" << elem_ << " offset:" << offset_
os << "iterator<" << nBits << "> ["
<< (index_ * packing() + offset_) << "]"
<< " index:" << index_ << " offset:" << offset_
<< " value:" << unsigned(*this)
<< nl;
@ -90,27 +91,41 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
os << get(i) << ' ';
}
label packLen = packedLength(size());
os << ")\n"
<< "storage: " << storage().size() << "( ";
<< "storage: " << packLen << "/" << storage().size() << "( ";
label count = size();
// mask for the valid bits
unsigned int validBits = max_value();
for (unsigned int i = 1; i < packing(); ++i)
{
validBits |= (validBits << nBits);
}
forAll(storage(), i)
for (label i=0; i < packLen; i++)
{
const PackedStorage& rawBits = storage()[i];
// create mask for unaddressed bits
unsigned int addressed = 0;
for (unsigned packI = 0; count && packI < packing(); packI++, count--)
// the final storage may not be full, modify validBits accordingly
if (i+1 == packLen)
{
addressed <<= nBits;
addressed |= max_value();
label junk = size() % packing();
if (junk)
{
junk = packing() - junk;
}
for (label j=0; j < junk; j++)
{
validBits >>= nBits;
}
}
for (unsigned int testBit = 0x1 << max_bits(); testBit; testBit >>= 1)
{
if (testBit & addressed)
if (testBit & validBits)
{
if (rawBits & testBit)
{
@ -123,7 +138,7 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
}
else
{
os << '_';
os << '.';
}
}
cout << ' ';
@ -156,7 +171,6 @@ void Foam::PackedList<nBits>::operator=(const UList<label>& lst)
}
// * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
//template<int nBits>

View File

@ -28,19 +28,31 @@ Class
Description
A Dynamically allocatable list of packed unsigned ints.
Gets given the number of bits per item.
Note
The list resizing is similar to DynamicList, thus the methods clear()
and setSize() behave like their DynamicList counterparts and the methods
reserve() and setCapacity() can be used to influence the allocation.
The number of bits per item is specified by the template parameter nBits.
Note
The iterator '()' dereferencing operator returns a proxy class that handles
assignment. However, the iterator itself can also handle assignment
directly and also returns a bool as per the set() methods.
Thus the following bit of code works as expected:
@code
blist[5] = 4;
changed = (blist[5] = 10);
changed = blist.set(5, 8);
@endcode
Using set() might be more readable (as expected) though.
SeeAlso
Foam::DynamicList
ToDo
Add checks for bad template parameters (ie, nBits=0, nBits too large).
The missing const_iterator might eventually still be needed.
Checks for bad template parameters (ie, nBits=0, nBits too large)?
SourceFiles
PackedListI.H
@ -110,10 +122,9 @@ public:
//- The number of entries per packed storage element
inline static unsigned int packing();
// Forward declaration of iterator
// Forward declaration of iterator and const_iterator
class iterator;
friend class iterator;
class const_iterator;
// Constructors
@ -152,11 +163,11 @@ public:
inline bool empty() const;
//- Get value at index I.
// Does not auto-vivifies entries.
// Does not auto-vivify entries.
inline unsigned int get(const label) const;
//- Set value at index I. Return true if value changed.
// Does not auto-vivifies entries.
// Does not auto-vivify entries.
inline bool set(const label, const unsigned int val);
//- Return the underlying packed storage
@ -185,7 +196,7 @@ public:
//- Reserve allocation space for at least this size.
// Never shrinks the allocated size.
// Optionally provide an initialization value for new elements.
inline void reserve(const label, const unsigned int& val = 0);
inline void reserve(const label);
//- Clear the list, i.e. set addressable size to zero.
// Does not adjust the underlying storage
@ -209,17 +220,19 @@ public:
//- Append a value at the end of the list
inline void append(const unsigned int val);
//- Remove and return the last element
inline unsigned int remove();
//- Get value at index I
// Auto-vivifies any new values to zero.
// Does not auto-vivify elements.
inline unsigned int operator[](const label) const;
//- Set value at index I.
// Returns proxy to perform the actual operation.
// Returns iterator to perform the actual operation.
// Auto-vivifies any new values to zero.
inline iterator operator[](const label);
//- Assignment of all entries to the given value.
// Does set on all elements.
//- Assignment of all entries to the given value. Takes linear time.
inline void operator=(const unsigned int val);
//- Assignment operator. Takes linear time.
@ -233,66 +246,136 @@ public:
// // Write PackedList to Ostream.
// friend Ostream& operator<< <nBits> (Ostream&, const PackedList<nBits>&);
//- The iterator-like class used for PackedList
class iterator
//- The const_iterator for PackedList
// Note: make data and functions protected, to allow reuse by iterator.
// Try not to be disturbed by non-const methods such as set(), they are
// just inherited by iterator.
class const_iterator
{
friend class PackedList;
// Private Data
protected:
// Protected Data
//- Reference to original list
PackedList& list_;
//- Element index within storage
unsigned elem_;
unsigned index_;
//- Offset within storage element
unsigned offset_;
//- Return the raw storage element
inline PackedStorage& chunk() const;
// Protected Member Functions
//- Return the position in the PackedList
inline label position() const;
//- Get value as unsigned
inline unsigned int get() const;
//- Set value, returning true if changed
// This is obviously used by iterator and not by const_iterator
inline bool set(unsigned int);
public:
// Constructors
//- Construct from base list and position index
inline iterator(const PackedList&, const label i);
inline const_iterator(const PackedList&, const label);
// Members
//- Construct from non-const iterator
explicit inline const_iterator(const iterator&);
//- Assign value, returns true if the value changed
inline bool operator=(const unsigned int val);
// Member operators
inline bool operator==(const const_iterator&) const;
inline bool operator!=(const const_iterator&) const;
//- Return referenced value directly
inline unsigned int operator*() const;
//- Return referenced value directly
inline unsigned int operator()() const;
inline const_iterator& operator++();
inline const_iterator operator++(int);
//- Conversion operator
inline operator unsigned int () const;
//- 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
//- const_iterator set to the beginning of the PackedList
inline const_iterator cbegin() const;
//- const_iterator set to beyond the end of the PackedList
inline const_iterator cend() const;
//- const_iterator set to the beginning of the PackedList
inline const_iterator begin() const;
//- const_iterator set to beyond the end of the PackedList
inline const_iterator end() const;
//- The iterator class used for PackedList
class iterator
:
public const_iterator
{
friend class PackedList;
//- A private proxy reference to the iterator, used for setting values
// Also provides a uniform target for the iterator 'operator*'
// and 'operator()' methods
class iteratorProxy
{
iterator* iter_;
public:
//- Construct from pointer to iterator
inline iteratorProxy(iterator*);
//- Assign value, returns true if the value changed
inline bool 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);
// Member Operators
inline void operator=(const iterator&);
//- Assign value directly, returns true if the value changed
inline bool 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);
};
//- iterator set to the beginning of the PackedList
inline iterator begin();
//- iterator set to beyond the end of the HashTable
@ -300,6 +383,7 @@ public:
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -26,27 +26,28 @@ License
\*---------------------------------------------------------------------------*/
#include "error.H"
#include <climits>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<int nBits>
inline unsigned int Foam::PackedList<nBits>::max_bits()
{
return sizeof(PackedStorage)*8 - 1;
return sizeof(PackedStorage)*CHAR_BIT - 1;
}
template<int nBits>
inline unsigned int Foam::PackedList<nBits>::max_value()
{
return ((1u << nBits) - 1);
return (1u << nBits) - 1;
}
template<int nBits>
inline unsigned int Foam::PackedList<nBits>::packing()
{
return sizeof(PackedStorage)*8 / nBits;
return sizeof(PackedStorage)*CHAR_BIT / nBits;
}
@ -119,43 +120,66 @@ Foam::PackedList<nBits>::clone() const
// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
template<int nBits>
inline Foam::PackedList<nBits>::iterator::iterator
inline Foam::PackedList<nBits>::const_iterator::const_iterator
(
const PackedList<nBits>& lst,
const label i
)
:
list_(const_cast<PackedList<nBits>&>(lst)),
elem_(i / packing()),
index_(i / packing()),
offset_(i % packing())
{}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::iterator
(
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 void Foam::PackedList<nBits>::iterator::operator=
(
const iterator& iter
const iterator& it
)
{
elem_ = iter.elem_;
offset_ = iter.offset_;
this->index_ = it.index_;
this->offset_ = it.offset_;
}
template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::operator==
inline bool Foam::PackedList<nBits>::const_iterator::operator==
(
const iterator& iter
const const_iterator& iter
) const
{
return elem_ == iter.elem_ && offset_ == iter.offset_;
return index_ == iter.index_ && offset_ == iter.offset_;
}
template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::operator!=
inline bool Foam::PackedList<nBits>::const_iterator::operator!=
(
const iterator& iter
const const_iterator& iter
) const
{
return !(operator==(iter));
@ -163,35 +187,40 @@ inline bool Foam::PackedList<nBits>::iterator::operator!=
template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::operator=
(
const unsigned int val
)
inline unsigned int Foam::PackedList<nBits>::const_iterator::get() const
{
const unsigned int& stored = list_.List<PackedStorage>::operator[](index_);
return (stored >> (nBits * offset_)) & max_value();
}
template<int nBits>
inline bool Foam::PackedList<nBits>::const_iterator::set(const unsigned int val)
{
unsigned int& stored = list_.List<PackedStorage>::operator[](index_);
const unsigned int prev = stored;
const unsigned int startBit = nBits * offset_;
const unsigned int mask = max_value() << startBit;
const unsigned int maskNew = max_value() << startBit;
unsigned int& stored = chunk();
const unsigned int old = stored;
stored &= ~mask;
stored |= (val << startBit) & mask;
return (old != stored);
stored = (stored & ~maskNew) | (maskNew & (val << startBit));
return prev != 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
inline typename Foam::PackedList<nBits>::const_iterator&
Foam::PackedList<nBits>::const_iterator::operator++()
{
return list_.List<PackedStorage>::operator[](elem_);
offset_++;
if (offset_ >= packing())
{
offset_ = 0;
index_++;
}
return *this;
}
@ -199,20 +228,27 @@ template<int nBits>
inline typename Foam::PackedList<nBits>::iterator&
Foam::PackedList<nBits>::iterator::operator++()
{
if (position() < list_.size())
this->offset_++;
if (this->offset_ >= packing())
{
offset_++;
if (offset_ >= packing())
{
elem_++;
offset_ = 0;
}
this->offset_ = 0;
this->index_++;
}
return *this;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::const_iterator::operator++(int)
{
const_iterator old = *this;
++*this;
return old;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::iterator::operator++(int)
@ -225,25 +261,76 @@ Foam::PackedList<nBits>::iterator::operator++(int)
template<int nBits>
inline unsigned int
Foam::PackedList<nBits>::iterator::operator()() const
Foam::PackedList<nBits>::const_iterator::operator*() const
{
return (chunk() >> (nBits * offset_)) & max_value();
return get();
}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::operator
inline unsigned int
Foam::PackedList<nBits>::const_iterator::operator()() const
{
return 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 bool Foam::PackedList<nBits>::iterator::operator=(const unsigned int val)
{
return set(val);
}
template<int nBits>
inline Foam::PackedList<nBits>::const_iterator::operator
unsigned int () const
{
return (chunk() >> (nBits * offset_)) & max_value();
return get();
}
template<int nBits>
inline Foam::PackedList<nBits>::iterator::operator
bool() const
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 !!(chunk() >> (nBits * offset_)) & max_value();
return iter_->get();
}
template<int nBits>
inline bool Foam::PackedList<nBits>::iterator::iteratorProxy::operator=
(
const unsigned int val
)
{
return iter_->set(val);
}
@ -255,6 +342,22 @@ Foam::PackedList<nBits>::begin()
}
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::begin() const
{
return const_iterator(*this, 0);
}
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::cbegin() const
{
return const_iterator(*this, 0);
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::end()
@ -263,6 +366,22 @@ Foam::PackedList<nBits>::end()
}
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::end() const
{
return iterator(*this, size());
}
template<int nBits>
inline typename Foam::PackedList<nBits>::const_iterator
Foam::PackedList<nBits>::cend() const
{
return iterator(*this, size());
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<int nBits>
@ -286,7 +405,53 @@ inline void Foam::PackedList<nBits>::resize
const unsigned int& val
)
{
reserve(nElem, val);
reserve(nElem);
if (nElem > size_)
{
// fill new elements or newly exposed elements
if (size_)
{
// fill value for complete chunks
unsigned int fill = val & max_value();
for (unsigned int i = 1; i < packing(); ++i)
{
fill |= (fill << nBits);
}
unsigned begIdx = size_ / packing();
unsigned begOff = size_ % packing();
unsigned endIdx = nElem / packing();
// partial chunk, preserve existing value
if (begOff)
{
unsigned int maskOld = max_value();
for (unsigned int i = 1; i < begOff; ++i)
{
maskOld |= (maskOld << nBits);
}
List<PackedStorage>::operator[](begIdx) &= maskOld;
List<PackedStorage>::operator[](begIdx) |= ~maskOld & fill;
// continue with the next chunk
begIdx++;
}
// fill in complete elements
while (begIdx < endIdx)
{
List<PackedStorage>::operator[](begIdx++) = fill;
}
}
else
{
// no original size - simply flood-fill
operator=(val);
}
}
size_ = nElem;
}
@ -315,34 +480,18 @@ inline void Foam::PackedList<nBits>::setCapacity(const label nElem)
{
List<PackedStorage>::setSize(packedLength(nElem), 0u);
// truncates addressable section too
// truncate addressed size too?
if (size_ > nElem)
{
# 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);
}
}
}
template<int nBits>
inline void Foam::PackedList<nBits>::reserve
(
const label nElem,
const unsigned int& val
const label nElem
)
{
label len = packedLength(nElem);
@ -352,12 +501,6 @@ inline void Foam::PackedList<nBits>::reserve
{
List<PackedStorage>::setSize(len, 0);
}
// fill new elements
for (label i = size_; i < nElem; i++)
{
set(i, val);
}
}
@ -421,22 +564,14 @@ inline unsigned int Foam::PackedList<nBits>::get(const label i) const
checkIndex(i);
# endif
return iterator(*this, i)();
return const_iterator(*this, i).get();
}
template<int 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)();
}
return const_iterator(*this, i).get();
}
@ -460,7 +595,7 @@ inline bool Foam::PackedList<nBits>::set
}
# endif
return (iterator(*this, i) = val);
return iterator(*this, i).set(val);
}
@ -475,32 +610,60 @@ inline void Foam::PackedList<nBits>::append(const unsigned int val)
}
template<int nBits>
inline unsigned int Foam::PackedList<nBits>::remove()
{
label elemI = size_ - 1;
if (elemI < 0)
{
FatalErrorIn
(
"Foam::PackedList<nBits>::remove()"
) << "List is empty" << abort(FatalError);
}
const unsigned int val = const_iterator(*this, elemI).get();
resize(elemI);
return val;
}
template<int nBits>
inline typename Foam::PackedList<nBits>::iterator
Foam::PackedList<nBits>::operator[](const label i)
{
if (i >= size_)
{
setSize(i + 1);
resize(i + 1);
}
return iterator(*this, i);
}
template<int nBits>
inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
{
if (val)
{
forAll(*this, elemI)
// specialization for nBits=1 isn't worth the bother
unsigned int fill = val & max_value();
for (unsigned int i = 1; i < packing(); ++i)
{
set(elemI, val);
fill |= (fill << nBits);
}
List<PackedStorage>::operator=(fill);
}
else
{
List<PackedStorage>::operator=(val);
List<PackedStorage>::operator=(0u);
}
}