mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
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:
@ -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";
|
||||
|
||||
3
applications/test/PackedList2/Make/files
Normal file
3
applications/test/PackedList2/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
PackedListTest2.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/PackedListTest2
|
||||
0
applications/test/PackedList2/Make/options
Normal file
0
applications/test/PackedList2/Make/options
Normal file
337
applications/test/PackedList2/PackedListTest2.C
Normal file
337
applications/test/PackedList2/PackedListTest2.C
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user