ENH: Add PackedBoolList class (previously just a typedef)

ENH: adjust internal storage of PackedList to ensure that all unused
     internal storage elements are guaranteed to always be bit-wise
     zero. This makes the PackedBoolList implementation easier, and
     also greatly eases much of the book-keeping.
     Bits are now also zeroed on PackedList::clear()

Note: in PackedList, require packing at least 2 items otherwise it is
     more efficient to use a normal list.
This commit is contained in:
Mark Olesen 2010-07-28 14:50:17 +02:00
parent c91b71b521
commit e12581bffc
12 changed files with 1157 additions and 235 deletions

View File

@ -329,23 +329,42 @@ int main(int argc, char *argv[])
list3.print(Info);
List<bool> list4(4, true);
List<bool> list4(16, false);
{
const List<bool>& constLst = list4;
// fill with some values
forAll(list4, i)
{
list4[i] = i % 3;
}
const UList<bool>& constLst = list4;
Info<< "\ntest operator[] const with out-of-range index\n";
Info<< constLst << endl;
if (constLst[20])
if (constLst[100])
{
Info<< "[20] is true (unexpected)\n";
Info<< "[100] is true (unexpected)\n";
}
else
{
Info<< "[20] is false (expected) list size should be unchanged "
<< "(const)\n";
Info<< "[100] is false (expected) "
<< "list size should be unchanged (const)\n";
}
Info<< constLst << endl;
}
PackedBoolList listb(list4);
Info<< "copied from bool list " << endl;
listb.print(Info, true);
{
labelList indices = listb.used();
Info<< "indices: " << indices << endl;
}
Info<< "\n\nDone.\n";
return 0;

View File

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

View File

@ -0,0 +1,124 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 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 3 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, see <http://www.gnu.org/licenses/>.
Application
Description
\*---------------------------------------------------------------------------*/
#include "uLabel.H"
#include "IOstreams.H"
#include "PackedBoolList.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
PackedBoolList list1(20);
// set every other one on
forAll(list1, i)
{
list1[i] = i % 2;
}
Info<< "\nalternative bit pattern\n";
list1.print(Info, true);
PackedBoolList list2 = ~list1;
Info<< "\ncomplementary bit pattern\n";
list2.print(Info, true);
list2.resize(24, true);
list2.resize(28, false);
for (label i=0; i < 4; ++i)
{
list2[i] = true;
}
Info<< "\nresized with 4 true + 4 false, bottom 4 bits true\n";
list2.print(Info, true);
labelList list2Labels = list2.used();
Info<< "\noperator|\n";
(list1 | list2).print(Info, true);
Info<< "\noperator& : does trim\n";
(list1 & list2).print(Info, true);
Info<< "\noperator^\n";
(list1 ^ list2).print(Info, true);
Info<< "\noperator|=\n";
{
PackedBoolList list3 = list1;
(list3 |= list2).print(Info, true);
}
Info<< "\noperator|= with UList<label>\n";
{
PackedBoolList list3 = list1;
(list3 |= list2Labels).print(Info, true);
}
Info<< "\noperator&=\n";
{
PackedBoolList list3 = list1;
(list3 &= list2).print(Info, true);
}
Info<< "\noperator+=\n";
{
PackedBoolList list3 = list1;
(list3 += list2).print(Info, true);
}
Info<< "\noperator+= with UList<label>\n";
{
PackedBoolList list3 = list1;
(list3 += list2Labels).print(Info, true);
}
Info<< "\noperator-=\n";
{
PackedBoolList list3 = list1;
(list3 -= list2).print(Info, true);
}
Info<< "\noperator-= with UList<label>\n";
{
PackedBoolList list3 = list1;
(list3 -= list2Labels).print(Info, true);
}
return 0;
}
// ************************************************************************* //

View File

@ -67,6 +67,7 @@ containers/HashTables/HashTable/HashTableCore.C
containers/HashTables/StaticHashTable/StaticHashTableCore.C
containers/Lists/SortableList/ParSortableListName.C
containers/Lists/PackedList/PackedListName.C
containers/Lists/PackedList/APackedBoolList.C
containers/Lists/ListOps/ListOps.C
containers/LinkedLists/linkTypes/SLListBase/SLListBase.C
containers/LinkedLists/linkTypes/DLListBase/DLListBase.C

View File

@ -0,0 +1,274 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 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 3 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, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "PackedBoolList.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
Foam::Xfer<Foam::labelList> Foam::PackedBoolList::used() const
{
labelList lst(this->count());
if (lst.size())
{
label nElem = 0;
forAll(*this, elemI)
{
if (get(elemI))
{
lst[nElem++] = elemI;
}
}
lst.setSize(nElem);
}
return lst.xfer();
}
template<class LabelListType>
Foam::label Foam::PackedBoolList::setFromIndices(const LabelListType& indices)
{
// no better information, just guess something about the size
reserve(indices.size());
label cnt = 0;
forAll(indices, elemI)
{
if (set(indices[elemI]))
{
++cnt;
}
}
return cnt;
}
template<class LabelListType>
Foam::label Foam::PackedBoolList::unsetFromIndices(const LabelListType& indices)
{
label cnt = 0;
forAll(indices, elemI)
{
if (unset(indices[elemI]))
{
++cnt;
}
}
return cnt;
}
Foam::label Foam::PackedBoolList::set(const UList<label>& indices)
{
return setFromIndices(indices);
}
Foam::label Foam::PackedBoolList::set(const UIndirectList<label>& indices)
{
return setFromIndices(indices);
}
Foam::label Foam::PackedBoolList::unset(const UList<label>& indices)
{
return unsetFromIndices(indices);
}
Foam::label Foam::PackedBoolList::unset(const UIndirectList<label>& indices)
{
return unsetFromIndices(indices);
}
void Foam::PackedBoolList::modulo(const PackedList<1>& lst)
{
// operate directly with the underlying storage
StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage();
const label len = min(rhs.size(), lhs.size());
for (label i=0; i < len; ++i)
{
lhs[i] &= ~rhs[i];
}
}
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
Foam::PackedBoolList&
Foam::PackedBoolList::operator=(const UList<bool>& lst)
{
this->setSize(lst.size());
forAll(*this, elemI)
{
set(elemI, lst[elemI]);
}
return *this;
}
Foam::PackedBoolList&
Foam::PackedBoolList::operator=(const UList<label>& indices)
{
clear();
set(indices);
return *this;
}
Foam::PackedBoolList&
Foam::PackedBoolList::operator=(const UIndirectList<label>& indices)
{
clear();
set(indices);
return *this;
}
Foam::PackedBoolList&
Foam::PackedBoolList::operator|=(const PackedList<1>& lst)
{
// extend addressable area if needed
if (this->size() < lst.size())
{
this->resize(lst.size());
}
// operate directly with the underlying storage
StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage();
forAll(rhs, i)
{
lhs[i] |= rhs[i];
}
return *this;
}
Foam::PackedBoolList&
Foam::PackedBoolList::operator&=(const PackedList<1>& lst)
{
// shrink addressable area if needed
if (this->size() > lst.size())
{
this->resize(lst.size());
}
// operate directly with the underlying storage
StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage();
forAll(lhs, i)
{
lhs[i] &= rhs[i];
}
// trim to bits actually used
this->trim();
return *this;
}
Foam::PackedBoolList&
Foam::PackedBoolList::operator^=(const PackedList<1>& lst)
{
// extend addressable area if needed
if (this->size() < lst.size())
{
this->resize(lst.size());
}
// operate directly with the underlying storage
StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage();
forAll(rhs, i)
{
lhs[i] ^= rhs[i];
}
return *this;
}
// * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * * //
Foam::PackedBoolList Foam::operator|
(
const PackedBoolList& lst1,
const PackedBoolList& lst2
)
{
PackedBoolList result(lst1);
result |= lst2;
return result;
}
Foam::PackedBoolList Foam::operator&
(
const PackedBoolList& lst1,
const PackedBoolList& lst2
)
{
PackedBoolList result(lst1);
result &= lst2;
return result;
}
Foam::PackedBoolList Foam::operator^
(
const PackedBoolList& lst1,
const PackedBoolList& lst2
)
{
PackedBoolList result(lst1);
result ^= lst2;
return result;
}
// ************************************************************************* //

View File

@ -0,0 +1,261 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 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 3 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, see <http://www.gnu.org/licenses/>.
Class
Foam::PackedBoolList
Description
A bit-packed bool list
SourceFiles
PackedBoolListI.H
PackedBoolList.C
SeeAlso
Foam::PackedList
\*---------------------------------------------------------------------------*/
#ifndef PackedBoolList_H
#define PackedBoolList_H
#include "PackedList.H"
#include "UIndirectList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class PackedBoolList Declaration
\*---------------------------------------------------------------------------*/
class PackedBoolList
:
public PackedList<1>
{
// Private Member Functions
//- Modulo is everything that is not in lst
// This is equivalent to unsetting the bits specified in lst
void modulo(const PackedList<1>&);
//- Set the listed indices. Return number of elements changed.
// Does auto-vivify for non-existent entries.
template<class LabelListType>
label setFromIndices(const LabelListType& indices);
//- Unset the listed indices. Return number of elements changed.
// Never auto-vivify entries.
template<class LabelListType>
label unsetFromIndices(const LabelListType& indices);
public:
// Constructors
//- Construct null
inline PackedBoolList();
//- Construct with given size, initializes list to 0
explicit inline PackedBoolList(const label size);
//- Construct with given size and value for all elements
inline PackedBoolList(const label size, const bool val);
//- Copy constructor
inline PackedBoolList(const PackedBoolList&);
//- Copy constructor
explicit inline PackedBoolList(const PackedList<1>&);
//- Construct by transferring the parameter contents
inline PackedBoolList(const Xfer<PackedBoolList>&);
//- Construct by transferring the parameter contents
inline PackedBoolList(const Xfer<PackedList<1> >&);
//- Construct from a list of bools
explicit inline PackedBoolList(const UList<bool>&);
//- Construct from a list of labels
// using the labels as indices to indicate which bits are set
explicit inline PackedBoolList(const UList<label>& indices);
//- Construct from a list of labels
// using the labels as indices to indicate which bits are set
explicit inline PackedBoolList(const UIndirectList<label>& indices);
//- Clone
inline autoPtr<PackedBoolList> clone() const;
// Member Functions
// Access
//- Return indices of the used (true) elements as a list of labels
Xfer<labelList> used() const;
using PackedList<1>::set;
using PackedList<1>::unset;
//- Set the listed indices. Return number of elements changed.
// Does auto-vivify for non-existent entries.
label set(const UList<label>& indices);
//- Set the listed indices. Return number of elements changed.
// Does auto-vivify for non-existent entries.
label set(const UIndirectList<label>& indices);
//- Unset the listed indices. Return number of elements changed.
// Never auto-vivify entries.
label unset(const UList<label>& indices);
//- Unset the listed indices. Return number of elements changed.
// Never auto-vivify entries.
label unset(const UIndirectList<label>& indices);
// Edit
//- Transfer the contents of the argument list into this list
// and annul the argument list.
inline void transfer(PackedBoolList&);
//- Transfer the contents of the argument list into this list
// and annul the argument list.
inline void transfer(PackedList<1>&);
//- Transfer contents to the Xfer container
inline Xfer<PackedBoolList> xfer();
// Member Operators
//- Assignment of all entries to the given value.
inline PackedBoolList& operator=(const bool val);
//- Assignment operator.
inline PackedBoolList& operator=(const PackedBoolList&);
//- Assignment operator.
inline PackedBoolList& operator=(const PackedList<1>&);
//- Assignment operator.
PackedBoolList& operator=(const UList<bool>&);
//- Assignment operator,
// using the labels as indices to indicate which bits are set
PackedBoolList& operator=(const UList<label>& indices);
//- Assignment operator,
// using the labels as indices to indicate which bits are set
PackedBoolList& operator=(const UIndirectList<label>& indices);
//- Complement operator
inline PackedBoolList operator~() const;
//- Or operator (lists may be dissimilar sizes)
PackedBoolList& operator|=(const PackedList<1>&);
//- Or operator (lists may be dissimilar sizes),
// using the labels as indices to indicate which bits are set
inline PackedBoolList& operator|=(const UList<label>& indices);
//- Or operator (lists may be dissimilar sizes),
// using the labels as indices to indicate which bits are set
inline PackedBoolList& operator|=(const UIndirectList<label>&);
//- And operator (lists may be dissimilar sizes)
// The result is trimmed to the smallest intersecting size
PackedBoolList& operator&=(const PackedList<1>&);
//- And operator (lists may be dissimilar sizes)
// Only retain unique entries
PackedBoolList& operator^=(const PackedList<1>&);
//- Synonymous with the or operator
inline PackedBoolList& operator+=(const PackedList<1>&);
//- Synonymous with the or operator
inline PackedBoolList& operator+=(const UList<label>& indices);
//- Synonymous with the or operator
inline PackedBoolList& operator+=(const UIndirectList<label>&);
//- Remove entries from this list
inline PackedBoolList& operator-=(const PackedList<1>&);
//- Remove entries from this list
inline PackedBoolList& operator-=(const UList<label>& indices);
//- Remove entries from this list
inline PackedBoolList& operator-=(const UIndirectList<label>&);
};
// Global Operators
//- Combine lists
PackedBoolList operator|
(
const PackedBoolList& lst1,
const PackedBoolList& lst2
);
//- Intersect lists - the result is trimmed to the smallest intersecting size
PackedBoolList operator&
(
const PackedBoolList& lst1,
const PackedBoolList& lst2
);
//- Combine to form a unique list (xor)
PackedBoolList operator^
(
const PackedBoolList& lst1,
const PackedBoolList& lst2
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "PackedBoolListI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,217 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 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 3 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, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::PackedBoolList::PackedBoolList()
:
PackedList<1>()
{}
inline Foam::PackedBoolList::PackedBoolList(const label size)
:
PackedList<1>(size)
{}
inline Foam::PackedBoolList::PackedBoolList
(
const label size,
const bool val
)
:
PackedList<1>(size, (val ? 1u : 0u))
{}
inline Foam::PackedBoolList::PackedBoolList(const PackedBoolList& lst)
:
PackedList<1>(lst)
{}
inline Foam::PackedBoolList::PackedBoolList(const PackedList<1>& lst)
:
PackedList<1>(lst)
{}
inline Foam::PackedBoolList::PackedBoolList(const Xfer<PackedBoolList>& lst)
:
PackedList<1>()
{
transfer(lst());
}
inline Foam::PackedBoolList::PackedBoolList(const Xfer<PackedList<1> >& lst)
:
PackedList<1>(lst)
{}
inline Foam::PackedBoolList::PackedBoolList(const UList<label>& indices)
:
PackedList<1>(indices.size(), 0u)
{
set(indices);
}
inline Foam::PackedBoolList::PackedBoolList(const UIndirectList<label>& indices)
:
PackedList<1>(indices.size(), 0u)
{
set(indices);
}
inline Foam::autoPtr<Foam::PackedBoolList>
Foam::PackedBoolList::clone() const
{
return autoPtr<PackedBoolList>(new PackedBoolList(*this));
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline void Foam::PackedBoolList::transfer(PackedBoolList& lst)
{
PackedList<1>::transfer(static_cast<PackedList<1>&>(lst));
}
inline void Foam::PackedBoolList::transfer(PackedList<1>& lst)
{
PackedList<1>::transfer(lst);
}
inline Foam::Xfer<Foam::PackedBoolList> Foam::PackedBoolList::xfer()
{
return xferMove(*this);
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline Foam::PackedBoolList
Foam::PackedBoolList::operator~() const
{
PackedBoolList result(*this);
result.flip();
return result;
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator=(const bool val)
{
PackedList<1>::operator=(val);
return *this;
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator=(const PackedBoolList& lst)
{
PackedList<1>::operator=(lst);
return *this;
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator=(const PackedList<1>& lst)
{
PackedList<1>::operator=(lst);
return *this;
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator|=(const UList<label>& indices)
{
set(indices);
return *this;
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator|=(const UIndirectList<label>& indices)
{
set(indices);
return *this;
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator+=(const PackedList<1>& lst)
{
return this->operator|=(lst);
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator+=(const UList<label>& indices)
{
return this->operator|=(indices);
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator+=(const UIndirectList<label>& indices)
{
return this->operator|=(indices);
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator-=(const PackedList<1>& lst)
{
this->modulo(lst);
return *this;
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator-=(const UList<label>& indices)
{
unset(indices);
return *this;
}
inline Foam::PackedBoolList&
Foam::PackedBoolList::operator-=(const UIndirectList<label>& indices)
{
unset(indices);
return *this;
}
// ************************************************************************* //

View File

@ -33,7 +33,10 @@ Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val)
StorageList(packedLength(size), 0u),
size_(size)
{
operator=(val);
if (val)
{
operator=(val);
}
}
@ -82,25 +85,11 @@ unsigned int Foam::PackedList<nBits>::count() const
if (size_)
{
// mask value for complete segments
unsigned int mask = maskLower(packing());
const label packLen = packedLength(size_);
const unsigned int endSeg = size_ / packing();
const unsigned int endOff = size_ % packing();
// count bits in complete segments
for (unsigned i = 0; i < endSeg; ++i)
for (label i = 0; i < packLen; ++i)
{
register unsigned int bits = StorageList::operator[](i) & mask;
COUNT_PACKEDBITS(c, bits);
}
// count bits in partial segment
if (endOff)
{
mask = maskLower(endOff);
register unsigned int bits = StorageList::operator[](endSeg) & mask;
register unsigned int bits = StorageList::operator[](i);
COUNT_PACKEDBITS(c, bits);
}
}
@ -117,64 +106,61 @@ bool Foam::PackedList<nBits>::trim()
return false;
}
// mask value for complete segments
unsigned int mask = maskLower(packing());
const label oldSize = size_;
label currElem = packedLength(size_) - 1;
unsigned int endOff = size_ % packing();
// clear trailing bits on final segment
if (endOff)
for (label storeI = packedLength(size_) - 1; storeI >= 0; --storeI)
{
StorageList::operator[](currElem) &= maskLower(endOff);
}
size_ = storeI * packing();
unsigned int bits = StorageList::operator[](storeI);
// test entire segment
while (currElem > 0 && !(StorageList::operator[](currElem) &= mask))
{
currElem--;
}
// test segment
label newsize = (currElem + 1) * packing();
// mask for the final segment
mask = max_value() << (nBits * (packing() - 1));
for (endOff = packing(); endOff >= 1; --endOff, --newsize)
{
if (StorageList::operator[](currElem) & mask)
// found some bits
if (bits)
{
while (bits)
{
bits >>= nBits;
++size_;
}
break;
}
mask >>= nBits;
}
if (size_ == newsize)
{
return false;
}
size_ = newsize;
return false;
return (size_ != oldSize);
}
template<unsigned nBits>
void Foam::PackedList<nBits>::flip()
{
label packLen = packedLength(size_);
for (label i=0; i < packLen; i++)
if (!size_)
{
StorageList::operator[](i) = ~StorageList::operator[](i);
return;
}
// mask value for complete segments
const unsigned int mask = maskLower(packing());
const label packLen = packedLength(size_);
for (label i=0; i < packLen; ++i)
{
StorageList::operator[](i) = mask & ~StorageList::operator[](i);
}
// mask off the final partial segment
{
const unsigned int off = size_ % packing();
if (off)
{
const unsigned int seg = size_ / packing();
StorageList::operator[](seg) &= maskLower(off);
}
}
}
template<unsigned nBits>
Foam::labelList Foam::PackedList<nBits>::values() const
Foam::Xfer<Foam::labelList> Foam::PackedList<nBits>::values() const
{
labelList elems(size_);
@ -182,7 +168,8 @@ Foam::labelList Foam::PackedList<nBits>::values() const
{
elems[i] = get(i);
}
return elems;
return elems.xfer();
}
@ -201,7 +188,11 @@ Foam::Ostream& Foam::PackedList<nBits>::iteratorBase::print(Ostream& os) const
template<unsigned nBits>
Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
Foam::Ostream& Foam::PackedList<nBits>::print
(
Ostream& os,
const bool fullOutput
) const
{
const label packLen = packedLength(size_);
@ -215,45 +206,56 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
// mask value for complete segments
unsigned int mask = maskLower(packing());
const label outputLen = fullOutput ? StorageList::size() : packLen;
for (label i=0; i < packLen; i++)
for (label i=0; i < outputLen; ++i)
{
const StorageType& rawBits = StorageList::operator[](i);
// the final segment may not be full, modify mask accordingly
if (i+1 == packLen)
if (i == packLen-1)
{
unsigned int endOff = size_ % packing();
const unsigned int off = size_ % packing();
if (endOff)
if (off)
{
mask = maskLower(endOff);
}
else
{
continue;
mask = maskLower(off);
}
}
else if (i == packLen)
{
// no mask for unaddressed bit
mask = 0u;
}
for (unsigned int testBit = (1u << max_bits()); testBit; testBit >>= 1)
{
if (mask & testBit)
{
// addressable region
if (rawBits & testBit)
{
os << '1';
os << '1';
}
else
{
os << '-';
os << '-';
}
}
else
{
os << 'x';
if (rawBits & testBit)
{
os << '!';
}
else
{
os << '.';
}
}
}
os << '\n';
os << '\n';
}
os << ")\n";
@ -264,15 +266,18 @@ Foam::Ostream& Foam::PackedList<nBits>::print(Ostream& os) const
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<unsigned nBits>
void Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst)
Foam::PackedList<nBits>&
Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst)
{
StorageList::operator=(lst);
size_ = lst.size();
return *this;
}
template<unsigned nBits>
void Foam::PackedList<nBits>::operator=(const UList<label>& lst)
Foam::PackedList<nBits>&
Foam::PackedList<nBits>::operator=(const UList<label>& lst)
{
setCapacity(lst.size());
size_ = lst.size();
@ -281,19 +286,8 @@ void Foam::PackedList<nBits>::operator=(const UList<label>& lst)
{
set(i, lst[i]);
}
return *this;
}
// * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
//template<unsigned nBits>
//Foam::Ostream& ::Foam::operator<<(Ostream& os, const PackedList<nBits>& lst)
//{
// os << lst();
// return os;
//}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -72,6 +72,10 @@ Note
list[8] = 1;
@endcode
Also note that all unused internal storage elements are guaranteed to
always be bit-wise zero. This property must not be violated by any
inheriting classes.
SeeAlso
Foam::DynamicList
@ -114,12 +118,19 @@ class PackedList
:
private List<unsigned int>
{
protected:
typedef unsigned int StorageType;
typedef List<StorageType> StorageList;
//- nBits must be positive (non-zero) and fit within the storage
// For simplicity, assume 8-bit bytes
StaticAssert(nBits && nBits < (sizeof(StorageType) << 3));
private:
//- nBits must be positive (non-zero) and fit within the storage.
// For efficiency, however, require packing at least 2 items otherwise
// it is more efficient to use a normal list.
// Thus max nBits is 1/2 of the base storage size.
// For simplicity, assume 8-bit bytes in the assert.
StaticAssert(nBits && nBits <= (sizeof(StorageType) << 2));
// Private data
@ -163,20 +174,20 @@ public:
//- Null constructor
inline PackedList();
//- Construct with given size, initializes list to 0.
//- Construct with given size, initializes list to 0
explicit inline PackedList(const label size);
//- Construct with given size and value for all elements.
//- Construct with given size and value for all elements
PackedList(const label size, const unsigned val);
//- Copy constructor.
//- Copy constructor
inline PackedList(const PackedList<nBits>&);
//- Construct by transferring the parameter contents
inline PackedList(const Xfer<PackedList<nBits> >&);
//- Construct from a list of labels
explicit PackedList(const UList<label>&);
explicit inline PackedList(const UList<label>&);
//- Clone
inline autoPtr< PackedList<nBits> > clone() const;
@ -209,6 +220,7 @@ public:
inline bool unset(const label);
//- Return the underlying packed storage
// Manipulate with utmost caution
inline List<unsigned int>& storage();
//- Return the underlying packed storage
@ -219,20 +231,30 @@ public:
// http://en.wikipedia.org/wiki/Hamming_weight
unsigned int count() const;
//- Return the values as a labelList
labelList values() const;
//- Return the values as a list of labels
Xfer<labelList> values() const;
//- Print values and information
Ostream& print(Ostream&) const;
//- Print values and information, optionally output unused elements
//
// addressable bits:
// on: '1', off: '-'
//
// non-addressable bits:
// on: '!', off: '.'
//
Ostream& print(Ostream&, const bool fullOutput=false) const;
// Edit
//- Trim any trailing zero elements
bool trim();
//- Invert the bits in the addressable region.
//- Invert the bits in the addressable region
void flip();
//- Clear all bits
inline void reset();
//- Alter the size of the underlying storage.
// The addressed size will be truncated if needed to fit, but will
// remain otherwise untouched.
@ -240,10 +262,10 @@ public:
//- Reset addressable list size, does not shrink the allocated size.
// Optionally specify a value for new elements.
inline void resize(const label, const unsigned int& val = 0);
inline void resize(const label, const unsigned int& val = 0u);
//- Alias for resize()
inline void setSize(const label, const unsigned int& val = 0);
inline void setSize(const label, const unsigned int& val = 0u);
//- Reserve allocation space for at least this size.
// Never shrinks the allocated size.
@ -287,23 +309,13 @@ public:
inline iteratorBase operator[](const label);
//- Assignment of all entries to the given value. Takes linear time.
inline void operator=(const unsigned int val);
inline PackedList<nBits>& operator=(const unsigned int val);
//- Assignment operator. Takes linear time.
void operator=(const PackedList<nBits>&);
PackedList<nBits>& operator=(const PackedList<nBits>&);
//- Assignment operator. Takes linear time.
void operator=(const UList<label>&);
// Ostream operator
// // Write PackedList to Ostream.
// friend Ostream& operator<< <nBits>
// (
// Ostream&,
// const PackedList<nBits>&
// );
PackedList<nBits>& operator=(const UList<label>&);
// Iterators and helpers
@ -347,6 +359,12 @@ public:
public:
// Member Functions
//- Return the element index corresponding to the iterator
inline label key() const;
// Member Operators
//- Compare values (not positions)
@ -376,11 +394,12 @@ public:
public iteratorBase
{
//- Disallow copy constructor from const_iterator -
// violates const-ness!
//- Disallow copy constructor from const_iterator
// This would violate const-ness!
iterator(const const_iterator&);
//- Disallow assignment from const_iterator - violates const-ness!
//- Disallow assignment from const_iterator
// This would violate const-ness!
void operator=(const const_iterator&);

View File

@ -151,27 +151,34 @@ Foam::PackedList<nBits>::iteratorBase::set(const unsigned int val)
const unsigned int seg = index_ / packing();
const unsigned int off = index_ % packing();
const unsigned int startBit = nBits * off;
const unsigned int mask = max_value() << startBit;
unsigned int& stored = list_->StorageList::operator[](seg);
const unsigned int prev = stored;
const unsigned int startBit = nBits * off;
const unsigned int maskNew = max_value() << startBit;
if (val & ~max_value())
if (val >= max_value())
{
// overflow is max_value, fill everything
stored |= maskNew;
stored |= mask;
}
else
{
stored &= ~maskNew;
stored |= maskNew & (val << startBit);
stored &= ~mask;
stored |= mask & (val << startBit);
}
return prev != stored;
}
template<unsigned nBits>
inline Foam::label Foam::PackedList<nBits>::iteratorBase::key() const
{
return index_;
}
template<unsigned nBits>
inline bool Foam::PackedList<nBits>::iteratorBase::operator==
(
@ -564,24 +571,27 @@ inline bool Foam::PackedList<nBits>::empty() const
template<unsigned nBits>
inline void Foam::PackedList<nBits>::resize
(
const label nElem,
const label newSize,
const unsigned int& val
)
{
reserve(nElem);
reserve(newSize);
if (nElem > size_)
const label oldSize = size_;
size_ = newSize;
if (size_ > oldSize)
{
// fill new elements or newly exposed elements
if (size_)
if (val)
{
// fill value for complete segments
unsigned int fill = val;
if (fill & ~max_value())
if (val >= max_value())
{
// overflow is max_value, fill everything
fill = ~0u;
// fill everything
fill = maskLower(packing());
}
else
{
@ -591,36 +601,64 @@ inline void Foam::PackedList<nBits>::resize
}
}
unsigned int seg = size_ / packing();
unsigned int off = size_ % packing();
// partial segment, preserve existing value
if (off)
// fill in complete segments
const label oldLen = packedLength(oldSize);
const label newLen = packedLength(size_);
for (label i=oldLen; i < newLen; ++i)
{
unsigned int maskOld = maskLower(off);
StorageList::operator[](seg) &= maskOld;
StorageList::operator[](seg) |= ~maskOld & fill;
// continue with the next segment
seg++;
StorageList::operator[](i) = fill;
}
unsigned int endSeg = nElem / packing();
// fill in complete elements
while (seg < endSeg)
// finish previous partial segment, preserve existing value
{
StorageList::operator[](seg++) = fill;
const unsigned int off = oldSize % packing();
if (off)
{
const unsigned int seg = oldSize / packing();
const unsigned int mask = maskLower(off);
StorageList::operator[](seg) &= mask;
StorageList::operator[](seg) |= ~mask & fill;
}
}
// mask off the (new) final partial segment
{
const unsigned int off = size_ % packing();
if (off)
{
const unsigned int seg = size_ / packing();
StorageList::operator[](seg) &= maskLower(off);
}
}
}
else
{
// no original size - simply flood-fill
operator=(val);
}
}
else if (size_ < oldSize)
{
// resize shrinking
// - clear newly exposed elements
size_ = nElem;
// fill in complete segments
const label oldLen = packedLength(oldSize);
const label newLen = packedLength(size_);
for (label i=newLen; i < oldLen; ++i)
{
StorageList::operator[](i) = 0u;
}
// mask off the final partial segment
{
const unsigned int off = size_ % packing();
if (off)
{
const unsigned int seg = size_ / packing();
StorageList::operator[](seg) &= maskLower(off);
}
}
}
}
@ -648,10 +686,19 @@ inline void Foam::PackedList<nBits>::setCapacity(const label nElem)
{
StorageList::setSize(packedLength(nElem), 0u);
// truncate addressed size too?
// truncate addressed size too
if (size_ > nElem)
{
size_ = nElem;
// mask off the final partial segment
const unsigned int off = size_ % packing();
if (off)
{
const unsigned int seg = size_ / packing();
StorageList::operator[](seg) &= maskLower(off);
}
}
}
@ -662,7 +709,7 @@ inline void Foam::PackedList<nBits>::reserve
const label nElem
)
{
label len = packedLength(nElem);
const label len = packedLength(nElem);
// need more capacity?
if (len > StorageList::size())
@ -681,9 +728,17 @@ inline void Foam::PackedList<nBits>::reserve
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::reset()
{
StorageList::operator=(0u);
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::clear()
{
reset();
size_ = 0;
}
@ -699,7 +754,7 @@ inline void Foam::PackedList<nBits>::clearStorage()
template<unsigned nBits>
inline void Foam::PackedList<nBits>::shrink()
{
label len = packedLength(size_);
const label len = packedLength(size_);
// we have unused space?
if (len < StorageList::size())
@ -820,7 +875,7 @@ inline bool Foam::PackedList<nBits>::unset(const label i)
template<unsigned nBits>
inline void Foam::PackedList<nBits>::append(const unsigned int val)
{
label elemI = size_;
const label elemI = size_;
reserve(elemI + 1);
size_++;
@ -855,35 +910,20 @@ Foam::PackedList<nBits>::operator[](const label i)
}
namespace Foam
{
// specialization for nBits=1
template<>
inline void Foam::PackedList<1>::operator=(const unsigned int val)
{
if (val)
{
StorageList::operator=(~0u);
}
else
{
StorageList::operator=(0u);
}
}
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
inline Foam::PackedList<nBits>&
Foam::PackedList<nBits>::operator=(const unsigned int val)
{
if (val)
const label packLen = packedLength(size_);
if (val && size_)
{
unsigned int fill = val;
if (fill & ~max_value())
if (val >= max_value())
{
// treat overflow as max_value
fill = ~0u;
// fill everything
fill = maskLower(packing());
}
else
{
@ -893,12 +933,31 @@ inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
}
}
StorageList::operator=(fill);
for (label i=0; i < packLen; ++i)
{
StorageList::operator[](i) = fill;
}
// mask off the final partial segment
{
const unsigned int off = size_ % packing();
if (off)
{
const unsigned int seg = size_ / packing();
StorageList::operator[](seg) &= maskLower(off);
}
}
}
else
{
StorageList::operator=(0u);
for (label i=0; i < packLen; ++i)
{
StorageList::operator[](i) = 0u;
}
}
return *this;
}

View File

@ -1,49 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2010 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 3 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, see <http://www.gnu.org/licenses/>.
Typedef
Foam::PackedBoolList
Description
A bit-packed bool list
\*---------------------------------------------------------------------------*/
#ifndef PackedBoolList_H
#define PackedBoolList_H
#include "bool.H"
#include "PackedList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef PackedList<> PackedBoolList;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //