Commit e12581bf authored by Mark Olesen's avatar Mark Olesen
Browse files

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.
parent c91b71b5
......@@ -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;
......
PackedListTest4.C
EXE = $(FOAM_USER_APPBIN)/PackedListTest4
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -21,29 +21,104 @@ License
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
Application
Description
A bit-packed bool list
\*---------------------------------------------------------------------------*/
#ifndef PackedBoolList_H
#define PackedBoolList_H
#include "uLabel.H"
#include "IOstreams.H"
#include "PackedBoolList.H"
#include "bool.H"
#include "PackedList.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
namespace Foam
int main(int argc, char *argv[])
{
typedef PackedList<> PackedBoolList;
}
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;
}
#endif
// ************************************************************************* //
......@@ -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
......
/*---------------------------------------------------------------------------*\
========= |
\\ / 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;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / 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