ENH: new bitSet class and improved PackedList class (closes #751)

- The bitSet class replaces the old PackedBoolList class.
  The redesign provides better block-wise access and reduced method
  calls. This helps both in cases where the bitSet may be relatively
  sparse, and in cases where advantage of contiguous operations can be
  made. This makes it easier to work with a bitSet as top-level object.

  In addition to the previously available count() method to determine
  if a bitSet is being used, now have simpler queries:

    - all()  - true if all bits in the addressable range are empty
    - any()  - true if any bits are set at all.
    - none() - true if no bits are set.

  These are faster than count() and allow early termination.

  The new test() method tests the value of a single bit position and
  returns a bool without any ambiguity caused by the return type
  (like the get() method), nor the const/non-const access (like
  operator[] has). The name corresponds to what std::bitset uses.

  The new find_first(), find_last(), find_next() methods provide a faster
  means of searching for bits that are set.

  This can be especially useful when using a bitSet to control an
  conditional:

  OLD (with macro):

      forAll(selected, celli)
      {
          if (selected[celli])
          {
              sumVol += mesh_.cellVolumes()[celli];
          }
      }

  NEW (with const_iterator):

      for (const label celli : selected)
      {
          sumVol += mesh_.cellVolumes()[celli];
      }

      or manually

      for
      (
          label celli = selected.find_first();
          celli != -1;
          celli = selected.find_next()
      )
      {
          sumVol += mesh_.cellVolumes()[celli];
      }

- When marking up contiguous parts of a bitset, an interval can be
  represented more efficiently as a labelRange of start/size.
  For example,

  OLD:

      if (isA<processorPolyPatch>(pp))
      {
          forAll(pp, i)
          {
              ignoreFaces.set(i);
          }
      }

  NEW:

      if (isA<processorPolyPatch>(pp))
      {
          ignoreFaces.set(pp.range());
      }
This commit is contained in:
Mark Olesen
2018-03-07 11:21:48 +01:00
parent 2768500d57
commit bac943e6fc
191 changed files with 4995 additions and 3151 deletions

View File

@ -122,7 +122,7 @@ int main(int argc, char *argv[])
fvc::makeAbsolute(phi, rho, U);
// Test : disable refinement for some cells
PackedBoolList& protectedCell =
bitSet& protectedCell =
refCast<dynamicRefineFvMesh>(mesh).protectedCell();
if (protectedCell.empty())

View File

@ -2,8 +2,8 @@
interpolationCellPoint<vector> UInterpolator(HbyA);
// Determine faces on outside of interpolated cells
PackedBoolList isOwnerInterpolatedFace(mesh.nInternalFaces());
PackedBoolList isNeiInterpolatedFace(mesh.nInternalFaces());
bitSet isOwnerInterpolatedFace(mesh.nInternalFaces());
bitSet isNeiInterpolatedFace(mesh.nInternalFaces());
// Determine donor cells
labelListList donorCell(mesh.nInternalFaces());
@ -175,11 +175,11 @@ surfaceVectorField faceNormals(mesh.Sf()/mesh.magSf());
forAll(isNeiInterpolatedFace, faceI)
{
label cellId = -1;
if (isNeiInterpolatedFace[faceI])
if (isNeiInterpolatedFace.test(faceI))
{
cellId = mesh.faceNeighbour()[faceI];
}
else if (isOwnerInterpolatedFace[faceI])
else if (isOwnerInterpolatedFace.test(faceI))
{
cellId = mesh.faceOwner()[faceI];
}

View File

@ -474,7 +474,7 @@ int main(int argc, char *argv[])
}
{
PackedBoolList select = HashSetOps::bitset(locations);
bitSet select = HashSetOps::bitset(locations);
auto output = ListOps::createWithValue<label>
(
30,
@ -482,8 +482,8 @@ int main(int argc, char *argv[])
100,
-1 // default value
);
Info<< "with PackedBoolList: " << flatOutput(output)
<< " selector: " << flatOutput(select.used()) << nl;
Info<< "with bitSet: " << flatOutput(output)
<< " selector: " << flatOutput(select.toc()) << nl;
}
{
@ -516,7 +516,7 @@ int main(int argc, char *argv[])
}
{
PackedBoolList select = HashSetOps::bitset(locations);
bitSet select = HashSetOps::bitset(locations);
auto output = ListOps::createWithValue<label>
(
30,
@ -524,7 +524,7 @@ int main(int argc, char *argv[])
100,
-1 // default value
);
Info<< "with PackedBoolList: " << flatOutput(output)
Info<< "with bitSet: " << flatOutput(output)
<< " selector: " << flatOutput(HashSetOps::used(select))
<< nl;
}

View File

@ -145,7 +145,7 @@ int main(int argc, char *argv[])
Info<<"Test reorder - oldToNew:" << nl
<< flatOutput(oldToNew) << nl << nl;
PackedBoolList bitset
bitSet bitset
(
ListOps::createWithValue<bool>
(

View File

@ -32,7 +32,7 @@ Description
#include "IOobject.H"
#include "IOstreams.H"
#include "IFstream.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include <climits>
@ -131,7 +131,7 @@ int main(int argc, char *argv[])
IFstream ifs(srcFile);
List<label> rawLst(ifs);
PackedBoolList packLst(rawLst);
bitSet packLst(rawLst);
Info<< "size: " << packLst.size() << nl;

View File

@ -28,61 +28,100 @@ Description
\*---------------------------------------------------------------------------*/
#include "uLabel.H"
#include "labelRange.H"
#include "bitSet.H"
#include "FlatOutput.H"
#include "IOstreams.H"
#include "PackedBoolList.H"
using namespace Foam;
template<unsigned Width>
inline Ostream& report
(
const PackedList<Width>& list,
bool showBits = false,
bool debugOutput = false
)
{
Info<< list.info();
if (showBits)
{
list.printBits(Info, debugOutput) << nl;
}
return Info;
}
inline Ostream& report
(
const bitSet& bitset,
bool showBits = false,
bool debugOutput = false
)
{
Info<< bitset.info();
Info<< "all:" << bitset.all()
<< " any:" << bitset.any()
<< " none:" << bitset.none() << nl;
if (showBits)
{
bitset.printBits(Info, debugOutput) << nl;
}
return Info;
}
// BitOps::printBits((Info<< list1.info()), true) << nl;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
Info<< "PackedList max_bits() = " << PackedList<>::max_bits() << nl;
Info<< "\ntest allocation with value\n";
PackedList<3> list1(5,1);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest assign uniform value\n";
list1 = 3;
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest assign uniform value (with overflow)\n";
list1 = -1;
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest zero\n";
list1 = 0;
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest set() with default argument (max_value)\n";
list1.set(1);
list1.set(3);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest unset() with in-range and out-of-range\n";
list1.unset(3);
list1.unset(100000);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest assign between references\n";
list1[2] = 3;
list1[4] = list1[2];
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest assign between references, with chaining\n";
list1[0] = 1;
list1[4] = 1;
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest assign between references, with chaining and auto-vivify\n";
list1[1] = 2;
list1[8] = 2;
list1[10] = 2;
list1[14] = 2;
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest operator== between references\n";
if (list1[1] == list1[8])
@ -106,7 +145,9 @@ int main(int argc, char *argv[])
{
const PackedList<3>& constLst = list1;
Info<< "\ntest operator[] const with out-of-range index\n";
constLst.printInfo(Info, true);
report(constLst);
if (constLst[20])
{
Info<< "[20] is true (unexpected)\n";
@ -116,7 +157,7 @@ int main(int argc, char *argv[])
Info<< "[20] is false (expected) list size should be unchanged "
<< "(const)\n";
}
constLst.printInfo(Info, true);
report(constLst);
Info<< "\ntest operator[] non-const with out-of-range index\n";
if (list1[20])
@ -128,7 +169,8 @@ int main(int argc, char *argv[])
Info<< "[20] is false (expected) but list was resized?? "
<< "(non-const)\n";
}
list1.printInfo(Info, true);
report(list1);
}
@ -137,94 +179,94 @@ int main(int argc, char *argv[])
{
Info<< "[20] is false, as expected\n";
}
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest resize with value (without reallocation)\n";
list1.resize(8, list1.max_value());
list1.printInfo(Info, true);
list1.resize(8, list1.max_value);
report(list1);
Info<< "\ntest flip() function\n";
list1.flip();
list1.printInfo(Info, true);
report(list1);
Info<< "\nre-flip()\n";
list1.flip();
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest set() function\n";
list1.set(1, 5);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest assign bool\n";
list1 = false;
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest assign bool\n";
list1 = true;
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest resize without value (with reallocation)\n";
list1.resize(12);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest resize with value (with reallocation)\n";
list1.resize(25, list1.max_value());
list1.printInfo(Info, true);
list1.resize(25, list1.max_value);
report(list1);
Info<< "\ntest resize smaller (should not touch allocation)\n";
list1.resize(8);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest append() operation\n";
list1.append(2);
list1.append(3);
list1.append(4);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest reserve() operation\n";
list1.reserve(32);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest shrink() operation\n";
list1.shrink();
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest setCapacity() operation\n";
list1.setCapacity(15);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest setCapacity() operation\n";
list1.setCapacity(100);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest operator[] assignment\n";
list1[16] = 5;
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest operator[] assignment with auto-vivify\n";
list1[36] = list1.max_value();
list1.printInfo(Info, true);
list1[36] = list1.max_value;
report(list1);
Info<< "\ntest setCapacity smaller\n";
list1.setCapacity(24);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest resize much smaller\n";
list1.resize(150);
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest trim\n";
list1.trim();
list1.printInfo(Info, true);
report(list1);
// add in some misc values
// Add in some misc values
list1[31] = 1;
list1[32] = 2;
list1[33] = 3;
Info<< "\ntest get() method\n";
Info<< "get(10):" << list1.get(10) << " and list[10]:" << list1[10] << "\n";
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest operator[] auto-vivify\n";
Info<< "size:" << list1.size() << "\n";
@ -234,33 +276,34 @@ int main(int argc, char *argv[])
Info<< "list[45]:" << val << "\n";
Info<< "size after read:" << list1.size() << "\n";
list1[45] = list1.max_value();
list1[45] = list1.max_value;
Info<< "size after write:" << list1.size() << "\n";
Info<< "list[45]:" << list1[45] << "\n";
list1[49] = list1[100];
list1.printInfo(Info, true);
report(list1);
Info<< "\ntest copy constructor + append\n";
PackedList<3> list2(list1);
list2.append(4);
Info<< "source list:\n";
list1.printInfo(Info, true);
report(list1);
Info<< "destination list:\n";
list2.printInfo(Info, true);
report(list2);
Info<< "\ntest pattern that fills all bits\n";
PackedList<4> list3(8, 8);
label pos = list3.size() - 1;
list3[pos--] = list3.max_value();
list3[pos--] = list3.max_value;
list3[pos--] = 0;
list3[pos--] = list3.max_value();
list3.printInfo(Info, true);
list3[pos--] = list3.max_value;
report(list3);
Info<< "removed final value: " << list3.remove() << endl;
list3.printInfo(Info, true);
report(list3);
Info<<"list: " << list3 << endl;
@ -289,18 +332,117 @@ int main(int argc, char *argv[])
}
PackedBoolList listb(list4);
bitSet listb(list4);
Info<< "copied from bool list " << endl;
listb.printInfo(Info, true);
// report(listb);
{
labelList indices = listb.used();
labelList indices = listb.toc();
Info<< "indices: " << indices << endl;
}
Info<< nl
<< "resizing: " << nl;
{
PackedList<1> list1(81, 1);
PackedList<3> list3(27, 5); // ie, 101
Info<< "initial" << nl; report(list1, true);
Info<< "initial" << nl; report(list3, true);
list1.resize(118, 1);
list3.resize(37, 3);
Info<< "extend with val" << nl; report(list1, true);
Info<< "extend with val" << nl; report(list3, true);
list1.resize(90, 0);
list3.resize(30, 4);
Info<< "contract with val" << nl; report(list1, true);
Info<< "contract with val" << nl; report(list3, true);
}
{
bitSet bits(45);
Info<< "bits" << nl; report(bits, true);
bits = true;
Info<< "bits" << nl; report(bits, true);
bits.unset(35);
Info<< "bits" << nl; report(bits, true);
bits.resize(39);
Info<< "bits" << nl; report(bits, true);
Info<< "values:" << flatOutput(bits.values()) << nl;
Info<< "used:" << flatOutput(bits.toc()) << nl;
bits.unset(labelRange(-15, 8));
Info<< "bits" << nl; report(bits, true);
bits.set(labelRange(-15, 100));
Info<< "bits" << nl; report(bits, true);
bits.set(labelRange(-15, 100));
Info<< "bits" << nl; report(bits, true);
bits.set(labelRange(150, 15));
Info<< "bits" << nl; report(bits, true);
bits.set(labelRange(0, 5));
Info<< "bits" << nl; report(bits, true);
bits.reset();
bits.resize(50);
Info<< "bits" << nl; report(bits, true);
bits.set(labelRange(4, 8));
Info<< "bits" << nl; report(bits, true);
bits.set(labelRange(30, 35));
Info<< "bits" << nl; report(bits, true);
bits.set(labelRange(80, 12));
Info<< "bits" << nl; report(bits, true);
bits.unset(labelRange(35, 16));
Info<< "bits" << nl; report(bits, true);
bits.unset(labelRange(0, 50));
bits.resize(100000);
bits.set(labelRange(30, 6));
bits[33] = false;
Info<<"used: " << flatOutput(bits.toc()) << endl;
Info<<"first: " << bits.find_first() << endl;
Info<<"next: " << bits.find_next(29) << endl;
Info<<"next: " << bits.find_next(30) << endl;
Info<<"next: " << bits.find_next(31) << endl;
Info<<"next: " << bits.find_next(31) << endl;
bits.set(labelRange(80, 10));
bits.resize(100);
Info<< "bits" << nl; report(bits, true);
bits.set(labelRange(125, 10));
Info<<"next: " << bits.find_next(64) << endl;
Info<<"used: " << flatOutput(bits.toc()) << endl;
for (const auto pos : bits)
{
Info<<"have: " << pos << nl;
}
}
Info<< "\n\nDone.\n";
return 0;

View File

@ -29,7 +29,7 @@ Description
#include "argList.H"
#include "boolList.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "HashSet.H"
#include "cpuTime.H"
#include <vector>
@ -63,7 +63,7 @@ int main(int argc, char *argv[])
unsigned long sum = 0;
PackedBoolList packed(n, 1);
bitSet packed(n, true);
boolList unpacked(n, true);
#ifdef TEST_STD_BOOLLIST

View File

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

View File

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

View File

@ -1,168 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ 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 "boolList.H"
#include "DynamicList.H"
#include "IOstreams.H"
#include "PackedBoolList.H"
#include "ITstream.H"
#include "StringStream.H"
#include "FlatOutput.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
PackedBoolList list1(20);
// set every third one on
forAll(list1, i)
{
list1[i] = !(i % 3);
}
Info<< "\nalternating bit pattern\n";
list1.printInfo(Info, true);
PackedBoolList list2(list1);
list2.flip();
Info<< "\nflipped bit pattern\n";
list2.printBits(Info);
// set every other on
forAll(list2, i)
{
list2[i] = !(i % 2);
}
Info<< "\nalternating bit pattern\n";
list2.printBits(Info);
list2.resize(28, false);
list2.resize(34, true);
list2.resize(40, false);
for (label i=0; i < 4; ++i)
{
list2[i] = true;
}
Info<< "\nresized with false, 6 true + 6 false, bottom 4 bits true\n";
list2.printInfo(Info, true);
labelList list2Labels = list2.used();
PackedBoolList list4
(
ITstream
(
"input",
"(1 n 1 n 1 n 1 1 off 0 0 f f 0 y yes y true y false on t)"
)()
);
Info<< "\ntest Istream constructor\n";
list4.printInfo(Info, true);
Info<< list4 << " indices: " << list4.used() << nl;
Info<< "\nassign from labelList\n";
list4.clear();
list4.setMany(labelList{0, 1, 2, 3, 12, 13, 14, 19, 20, 21});
list4.printInfo(Info, true);
Info<< list4 << " indices: " << list4.used() << nl;
// Not yet:
// PackedBoolList list5{0, 1, 2, 3, 12, 13, 14, 19, 20, 21};
// list5.printInfo(Info, true);
// Info<< list5 << " indices: " << list5.used() << nl;
Info<< "\nassign from indices\n";
list4.read
(
IStringStream
(
"{0 1 2 3 12 13 14 19 20 21}"
)()
);
list4.printInfo(Info, true);
Info<< list4 << " indices: " << list4.used() << nl;
boolList bools(list4.size());
forAll(list4, i)
{
bools[i] = list4[i];
}
Info<< "boolList: " << bools << nl;
// check roundabout assignments
PackedList<2> pl2
(
IStringStream
(
"{(0 3)(1 3)(2 3)(3 3)(12 3)(13 3)(14 3)(19 3)(20 3)(21 3)}"
)()
);
Info<< "roundabout assignment: " << pl2 << nl;
list4.clear();
forAll(pl2, i)
{
list4[i] = pl2[i];
}
list4.writeList(Info, -1) << nl; // indexed output
list4.writeEntry("PackedBoolList", Info);
// Construct from labelUList, labelUIndList
{
DynamicList<label> indices({10, 50, 300});
Info<< "set: " << flatOutput(indices) << endl;
PackedBoolList bools1(indices);
Info<< "used: " << bools1.size() << " "
<< flatOutput(bools1.used()) << endl;
}
return 0;
}
// ************************************************************************* //

View File

@ -218,7 +218,7 @@ int main(int argc, char *argv[])
labelList patchEdges;
labelList coupledEdges;
PackedBoolList sameEdgeOrientation;
bitSet sameEdgeOrientation;
PatchTools::matchEdges
(
pp,

View File

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

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -22,50 +22,60 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-bitSet1
Description
Test bitSet functionality
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "boolList.H"
#include "bitSet.H"
#include "HashSet.H"
#include "cpuTime.H"
#include "PackedBoolList.H"
#include <vector>
#include <unordered_set>
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
inline Ostream& report
(
const bitSet& bitset,
bool showBits = false,
bool debugOutput = false
)
{
Info<< "size=" << bitset.size() << "/" << bitset.capacity()
<< " count=" << bitset.count()
<< " all:" << bitset.all()
<< " any:" << bitset.any()
<< " none:" << bitset.none() << nl;
Info<< "values: " << flatOutput(bitset) << nl;
if (showBits)
{
bitset.printBits(Info, debugOutput) << nl;
}
return Info;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
const label nLoop = 5;
const label n = 100000000;
// const label nReport = 1000000;
bitSet set1(100);
cpuTime timer;
Info<<"bitSet(label): "; report(set1, true);
// test inserts
PackedBoolList packed;
for (label iloop = 0; iloop < nLoop; ++iloop)
{
for (label i = 0; i < n; ++i)
{
// if ((i % nReport) == 0 && i)
// {
// Info<< "." << flush;
// }
packed[i] = 1;
// Make compiler do something else too
packed[i/2] = 0;
}
}
Info<< nl
<< "insert test: " << nLoop << "*" << n << " elements in "
<< timer.cpuTimeIncrement() << " s\n\n";
bitSet set2(100, { -1, 10, 25, 45});
Info<<"bitSet(label, labels): "; report(set2, true);
Info << "\nEnd\n" << endl;
Info<< "End\n" << endl;
return 0;
}

View File

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

View File

@ -0,0 +1,311 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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
Test-bitSet2
Description
Test bitSet functionality
\*---------------------------------------------------------------------------*/
#include "uLabel.H"
#include "boolList.H"
#include "DynamicList.H"
#include "IOstreams.H"
#include "ITstream.H"
#include "StringStream.H"
#include "bitSet.H"
#include "FlatOutput.H"
using namespace Foam;
inline Ostream& report
(
const bitSet& bitset,
bool showBits = false,
bool debugOutput = false
)
{
Info<< "size=" << bitset.size() << "/" << bitset.capacity()
<< " count=" << bitset.count()
<< " all:" << bitset.all()
<< " any:" << bitset.any()
<< " none:" << bitset.none() << nl;
Info<< "values: " << flatOutput(bitset) << nl;
if (showBits)
{
bitset.printBits(Info, debugOutput) << nl;
}
return Info;
}
template<class UIntType>
std::string toString(UIntType value, char off='.', char on='1')
{
std::string str(std::numeric_limits<UIntType>::digits, off);
unsigned n = 0;
// Starting from most significant bit - makes for easy reading.
for
(
unsigned test = (1u << (std::numeric_limits<UIntType>::digits-1));
test;
test >>= 1u
)
{
str[n++] = ((value & test) ? on : off);
}
return str;
}
inline bool compare
(
const bitSet& bitset,
const std::string& expected
)
{
const List<unsigned int>& store = bitset.storage();
std::string has;
for (label blocki=0; blocki < bitset.nBlocks(); ++blocki)
{
has += toString(store[blocki]);
}
if (has == expected)
{
Info<< "pass: " << has << nl;
return true;
}
Info<< "fail: " << has << nl;
Info<< "expect: " << expected << nl;
return false;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
bitSet list1(22);
// Set every third one on
forAll(list1, i)
{
list1[i] = !(i % 3);
}
Info<< "\nalternating bit pattern\n";
compare(list1, "..........1..1..1..1..1..1..1..1");
list1.unset(labelRange(13, 20)); // In range
Info<< "\nafter clear [13,..]\n";
compare(list1, "...................1..1..1..1..1");
report(list1, true);
list1.unset(labelRange(40, 20)); // out of range
Info<< "\nafter clear [40,..]\n";
compare(list1, "...................1..1..1..1..1");
report(list1, true);
Info<< "first: " << list1.find_first()
<< " last: " << list1.find_last() << endl;
Info<< "iterate through:";
for (const label idx : list1)
{
Info<<" " << idx;
}
Info<< nl;
Info<< "\nalternating bit pattern\n";
report(list1, true);
bitSet list2 = ~list1;
Info<< "\nflipped bit pattern\n";
report(list2, true);
// set every other on
forAll(list2, i)
{
list2[i] = !(i % 2);
}
Info<< "\nstarting pattern\n";
report(list2, true);
list2.resize(28, false);
list2.resize(34, true);
list2.resize(40, false);
for (label i=0; i < 4; ++i)
{
list2[i] = true;
}
Info<< "\nresized with false, [28,34) true + 6 false, bottom 4 bits true\n";
compare
(
list2,
"1111.......1.1.1.1.1.1.1.1.11111"
"..............................11"
);
report(list2, true);
labelList list2Labels = list2.toc();
Info<< "\noperator|\n";
list1.printBits(Info);
list2.printBits(Info);
Info<< "==\n";
(list1 | list2).printBits(Info);
Info<< "\noperator& : does trim\n";
report((list1 & list2), true);
Info<< "\noperator^\n";
report((list1 ^ list2), true);
Info<< "\noperator|=\n";
{
bitSet list3 = list1;
report((list3 |= list2), true);
}
Info<< "\noperator&=\n";
{
bitSet list3 = list1;
report((list3 &= list2), true);
}
Info<< "\noperator^=\n";
{
bitSet list3 = list1;
report((list3 ^= list2), true);
}
Info<< "\noperator-=\n";
{
bitSet list3 = list1;
report((list3 -= list2), true);
}
bitSet list4
(
ITstream
(
"input",
"(1 n 1 n 1 n 1 1 off 0 0 f f 0 y yes y true y false on t)"
)()
);
Info<< "\ntest Istream constructor\n";
report(list4, true);
Info<< "\nclear/assign from labelList\n";
list4.clear();
list4.setMany(labelList{0, 1, 2, 3, 12, 13, 14, 19, 20, 21});
report(list4, true);
// Not yet:
// bitSet list5{0, 1, 2, 3, 12, 13, 14, 19, 20, 21};
// list5.printInfo(Info, true);
// Info<< list5 << " indices: " << list5.toc() << nl;
Info<< "\nassign from indices\n";
list4.read
(
IStringStream
(
"{0 1 2 3 12 13 14 19 20 21}"
)()
);
report(list4, true);
compare(list4, "..........111....111........1111");
list4.set(labelRange(28, 6)); // extends size
Info<<"extended\n";
compare
(
list4,
"1111......111....111........1111"
"..............................11"
);
list4.set(labelRange(40, 6)); // extends size
Info<<"extended\n";
compare
(
list4,
"1111......111....111........1111"
"..................111111......11"
);
list4.unset(labelRange(14, 19));
Info<<"cleared [14,33)\n";
compare
(
list4,
"..................11........1111"
"..................111111......1."
);
// Construct from labelUList, labelUIndList
{
DynamicList<label> indices({10, 50, 300});
Info<< "set: " << flatOutput(indices) << endl;
bitSet bools1(indices);
Info<< "used: " << bools1.size() << " "
<< flatOutput(bools1.toc()) << endl;
}
return 0;
}
// ************************************************************************* //

View File

@ -27,6 +27,7 @@ Description
\*---------------------------------------------------------------------------*/
#include "bool.H"
#include "BitOps.H"
#include "IOstreams.H"
#include "stdFoam.H"
@ -177,6 +178,15 @@ int main(int argc, char *argv[])
printOffset<double>();
Info<<nl << "Test repeat_value" << nl << nl;
Info<< BitOps::bitInfo<unsigned>(BitOps::repeat_value<unsigned, 3>(1u))
<< nl;
Info<< BitOps::bitInfo<unsigned>(BitOps::repeat_value<unsigned>(1u))
<< nl;
Info << "---\nEnd\n" << endl;
return 0;

View File

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

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -22,44 +22,24 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Test the sizeof for basic types. Can be compiled and run without
any OpenFOAM libraries.
Test the sizeof for basic types.
Can be compiled and run without any OpenFOAM libraries.
g++ -std=c++11 -oTest-machine-sizes Test-machine-sizes.cpp
\*---------------------------------------------------------------------------*/
#include <cstdint>
#include <climits>
#include <cstdlib>
#include <limits>
#include <iostream>
// Can also compile without OpenFOAM
#ifdef WM_LABEL_SIZE
#include "IOstreams.H"
#endif
template<class T>
void print(const char* msg)
{
std::cout<< msg << ' ' << sizeof(T) << '\n';
}
#ifdef WM_LABEL_SIZE
template<class T>
void printMax(const char* msg)
{
std::cout<< msg << ' ' << sizeof(T)
<< " max "
<< std::numeric_limits<T>::max() << '\n';
Foam::Info<< msg << ' ' << sizeof(T)
<< " max "
<< long(std::numeric_limits<T>::max()) << '\n';
}
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
@ -67,42 +47,16 @@ int main(int argc, char *argv[])
{
std::cout<<"machine sizes\n---\n\n";
print<mode_t>("mode_t");
print<short>("short");
print<int>("int");
print<long>("long");
print<long long>("long long");
print<unsigned short>("ushort");
print<unsigned int>("uint");
print<unsigned long>("ulong");
print<unsigned long long>("ulong-long");
print<int16_t>("int16");
print<int32_t>("int32");
print<int64_t>("int64");
print<uint16_t>("uint16");
print<uint32_t>("uint32");
print<uint64_t>("uint64");
print<float>("float");
print<double>("double");
print<long double>("long double");
print<std::string>("std::string");
print<std::string::size_type>("std::string::size_type");
#ifdef WM_LABEL_SIZE
std::cout<<"\nmax values\n---\n\n";
printMax<mode_t>("mode_t");
Foam::Info<< "mode_t 0777: " << mode_t(0777) << '\n';
printMax<short>("short");
printMax<int>("int");
printMax<long>("long");
printMax<unsigned short>("ushort");
printMax<unsigned int>("uint");
printMax<unsigned long>("ulong");
printMax<float>("float");
printMax<double>("double");
#endif
std::cout << "\n---\nEnd\n\n";
return 0;

View File

@ -48,10 +48,6 @@ Usage
- \par -triSurface
Use triSurface library for input/output
- \par -keyed
Use keyedSurface for input/output
Note
The filename extensions are used to determine the file format type.
@ -64,7 +60,6 @@ Note
#include "surfMesh.H"
#include "surfFields.H"
#include "surfPointFields.H"
#include "PackedBoolList.H"
#include "MeshedSurfaces.H"
#include "ModifiableMeshedSurface.H"

View File

@ -406,13 +406,13 @@ void testPointSync(const polyMesh& mesh, Random& rndGen)
{
labelList nMasters(mesh.nPoints(), 0);
PackedBoolList isMasterPoint(syncTools::getMasterPoints(mesh));
bitSet isMasterPoint(syncTools::getMasterPoints(mesh));
forAll(isMasterPoint, pointi)
{
if (isMasterPoint[pointi])
if (isMasterPoint.test(pointi))
{
nMasters[pointi] = 1;
nMasters.set(pointi);
}
}
@ -482,13 +482,13 @@ void testEdgeSync(const polyMesh& mesh, Random& rndGen)
{
labelList nMasters(edges.size(), 0);
PackedBoolList isMasterEdge(syncTools::getMasterEdges(mesh));
bitSet isMasterEdge(syncTools::getMasterEdges(mesh));
forAll(isMasterEdge, edgeI)
{
if (isMasterEdge[edgeI])
if (isMasterEdge.test(edgeI))
{
nMasters[edgeI] = 1;
nMasters.set(edgeI);
}
}
@ -551,13 +551,13 @@ void testFaceSync(const polyMesh& mesh, Random& rndGen)
{
labelList nMasters(mesh.nFaces(), 0);
PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh));
Bitset isMasterFace(syncTools::getMasterFaces(mesh));
forAll(isMasterFace, facei)
{
if (isMasterFace[facei])
if (isMasterFace.test(facei))
{
nMasters[facei] = 1;
nMasters.set(facei);
}
}

View File

@ -81,7 +81,7 @@ void modifyOrAddFace
const label zoneID,
const bool zoneFlip,
PackedBoolList& modifiedFace
bitSet& modifiedFace
)
{
if (modifiedFace.set(facei))
@ -338,7 +338,7 @@ void subsetTopoSets
Info<< "Subsetting " << set.type() << " " << set.name() << endl;
// Map the data
PackedBoolList isSet(set.maxSize(mesh));
bitSet isSet(set.maxSize(mesh));
forAllConstIter(labelHashSet, set, iter)
{
isSet.set(iter.key());
@ -374,7 +374,7 @@ void createCoupledBaffles
fvMesh& mesh,
const labelList& coupledWantedPatch,
polyTopoChange& meshMod,
PackedBoolList& modifiedFace
bitSet& modifiedFace
)
{
const faceZoneMesh& faceZones = mesh.faceZones();
@ -442,7 +442,7 @@ void createCyclicCoupledBaffles
const labelList& cyclicMasterPatch,
const labelList& cyclicSlavePatch,
polyTopoChange& meshMod,
PackedBoolList& modifiedFace
bitSet& modifiedFace
)
{
const faceZoneMesh& faceZones = mesh.faceZones();
@ -1119,7 +1119,7 @@ int main(int argc, char *argv[])
// Whether first use of face (modify) or consecutive (add)
PackedBoolList modifiedFace(mesh.nFaces());
bitSet modifiedFace(mesh.nFaces());
// Create coupled wall-side baffles
createCoupledBaffles

View File

@ -366,7 +366,7 @@ void Foam::cellSplitter::setRefinement
// Mark off affected face.
boolList faceUpToDate(mesh_.nFaces(), true);
bitSet faceUpToDate(mesh_.nFaces(), true);
forAllConstIter(Map<point>, cellToMidPoint, iter)
{
@ -374,18 +374,15 @@ void Foam::cellSplitter::setRefinement
const cell& cFaces = mesh_.cells()[celli];
forAll(cFaces, i)
{
label facei = cFaces[i];
faceUpToDate[facei] = false;
}
faceUpToDate.unsetMany(cFaces);
}
forAll(faceUpToDate, facei)
{
if (!faceUpToDate[facei])
if (!faceUpToDate.test(facei))
{
faceUpToDate.set(facei);
const face& f = mesh_.faces()[facei];
if (mesh_.isInternalFace(facei))
@ -454,8 +451,6 @@ void Foam::cellSplitter::setRefinement
)
);
}
faceUpToDate[facei] = true;
}
}
}

View File

@ -579,7 +579,7 @@ int main(int argc, char *argv[])
pointField newPoints(points);
PackedBoolList collapseEdge(mesh.nEdges());
bitSet collapseEdge(mesh.nEdges());
Map<point> collapsePointToLocation(mesh.nPoints());
// Get new positions and construct collapse network

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -97,10 +97,10 @@ int main(int argc, char *argv[])
label nPatchFaces = 0;
label nPatchEdges = 0;
forAllConstIter(labelHashSet, patchSet, iter)
for (const label patchi : patchSet)
{
nPatchFaces += mesh.boundaryMesh()[iter.key()].size();
nPatchEdges += mesh.boundaryMesh()[iter.key()].nEdges();
nPatchFaces += mesh.boundaryMesh()[patchi].size();
nPatchEdges += mesh.boundaryMesh()[patchi].nEdges();
}
// Construct from estimate for the number of cells to refine
@ -111,15 +111,13 @@ int main(int argc, char *argv[])
DynamicList<scalar> allCutEdgeWeights(nPatchEdges);
// Find cells to refine
forAllConstIter(labelHashSet, patchSet, iter)
for (const label patchi : patchSet)
{
const polyPatch& pp = mesh.boundaryMesh()[iter.key()];
const polyPatch& pp = mesh.boundaryMesh()[patchi];
const labelList& meshPoints = pp.meshPoints();
forAll(meshPoints, pointi)
for (const label meshPointi : meshPoints)
{
label meshPointi = meshPoints[pointi];
const labelList& pCells = mesh.pointCells()[meshPointi];
cutCells.insertMany(pCells);
@ -139,49 +137,43 @@ int main(int argc, char *argv[])
<< cells.instance()/cells.local()/cells.name()
<< nl << endl;
forAllConstIter(cellSet, cells, iter)
for (const label celli : cells)
{
cutCells.erase(iter.key());
cutCells.erase(celli);
}
Info<< "Removed from cells to cut all the ones not in set "
<< setName << nl << endl;
}
// Mark all mesh points on patch
boolList vertOnPatch(mesh.nPoints(), false);
bitSet vertOnPatch(mesh.nPoints());
forAllConstIter(labelHashSet, patchSet, iter)
for (const label patchi : patchSet)
{
const polyPatch& pp = mesh.boundaryMesh()[iter.key()];
const polyPatch& pp = mesh.boundaryMesh()[patchi];
const labelList& meshPoints = pp.meshPoints();
forAll(meshPoints, pointi)
{
vertOnPatch[meshPoints[pointi]] = true;
}
vertOnPatch.setMany(meshPoints);
}
forAllConstIter(labelHashSet, patchSet, iter)
for (const label patchi : patchSet)
{
const polyPatch& pp = mesh.boundaryMesh()[iter.key()];
const polyPatch& pp = mesh.boundaryMesh()[patchi];
const labelList& meshPoints = pp.meshPoints();
forAll(meshPoints, pointi)
for (const label meshPointi : meshPoints)
{
label meshPointi = meshPoints[pointi];
const labelList& pEdges = mesh.pointEdges()[meshPointi];
forAll(pEdges, pEdgeI)
for (const label edgei : pEdges)
{
const label edgeI = pEdges[pEdgeI];
const edge& e = mesh.edges()[edgeI];
const edge& e = mesh.edges()[edgei];
label otherPointi = e.otherVertex(meshPointi);
if (!vertOnPatch[otherPointi])
if (!vertOnPatch.test(otherPointi))
{
allCutEdges.append(edgeI);
allCutEdges.append(edgei);
if (e.start() == meshPointi)
{
@ -214,7 +206,7 @@ int main(int argc, char *argv[])
(
mesh,
cutCells.toc(), // cells candidate for cutting
labelList(0), // cut vertices
labelList(), // cut vertices
allCutEdges, // cut edges
cutEdgeWeights // weight on cut edges
);

View File

@ -869,7 +869,7 @@ int main(int argc, char *argv[])
// Pre-filtering: flip "owner" boundary or wrong oriented internal
// faces and move to neighbour
boolList fm(faces.size(), false);
bitSet fm(faces.size(), false);
forAll(faces, facei)
{
if
@ -878,7 +878,7 @@ int main(int argc, char *argv[])
|| (neighbour[facei] != -1 && owner[facei] > neighbour[facei])
)
{
fm[facei] = true;
fm.set(facei);
if (!cubitFile)
{
faces[facei].flip();
@ -1279,7 +1279,7 @@ int main(int argc, char *argv[])
false, // flipFaceFlux
-1, // patchID
faceZonei, // zoneID
fm[facei] // zoneFlip
fm.test(facei) // zoneFlip
);
}

View File

@ -1620,14 +1620,14 @@ int main(int argc, char *argv[])
labelList cls(end() - start() + 1);
// Mark zone cells, used for finding faces
boolList zoneCell(pShapeMesh.nCells(), false);
bitSet zoneCell(pShapeMesh.nCells(), false);
// shift cell indizes by 1
label nr=0;
for (label celli = (start() - 1); celli < end(); celli++)
{
cls[nr]=celli;
zoneCell[celli] = true;
zoneCell.set(celli);
nr++;
}
@ -1646,7 +1646,7 @@ int main(int argc, char *argv[])
label own = pShapeMesh.faceOwner()[facei];
if (nei != -1)
{
if (zoneCell[nei] && zoneCell[own])
if (zoneCell.test(nei) && zoneCell.test(own))
{
zoneFaces.append(facei);
}
@ -1669,7 +1669,7 @@ int main(int argc, char *argv[])
const labelList& faceCells = bPatches[pI].faceCells();
forAll(faceCells, fcI)
{
if (zoneCell[faceCells[fcI] ])
if (zoneCell.test(faceCells[fcI]))
{
boundaryZones[pI].append(name);
break;

View File

@ -890,7 +890,7 @@ int main(int argc, char *argv[])
const edgeList& edges = mesh.edges();
const pointField& points = mesh.points();
PackedBoolList collapseEdge(mesh.nEdges());
bitSet collapseEdge(mesh.nEdges());
Map<point> collapsePointToLocation(mesh.nPoints());
forAll(edges, edgeI)

View File

@ -1268,7 +1268,7 @@ void extrudeGeometricProperties
// Determine edge normals on original patch
labelList patchEdges;
labelList coupledEdges;
PackedBoolList sameEdgeOrientation;
bitSet sameEdgeOrientation;
PatchTools::matchEdges
(
extrudePatch,
@ -2160,7 +2160,7 @@ int main(int argc, char *argv[])
labelListList extrudeEdgePatches(extrudePatch.nEdges());
// Is edge a non-manifold edge
PackedBoolList nonManifoldEdge(extrudePatch.nEdges());
bitSet nonManifoldEdge(extrudePatch.nEdges());
// Note: logic has to be same as in countExtrudePatches.
forAll(edgeFaces, edgeI)

View File

@ -256,7 +256,7 @@ int main(int argc, char *argv[])
const boundBox& bb = mesh().bounds();
const scalar mergeDim = 1e-4 * bb.minDim();
PackedBoolList collapseEdge(mesh().nEdges());
bitSet collapseEdge(mesh().nEdges());
Map<point> collapsePointToLocation(mesh().nPoints());
forAll(edges, edgeI)

View File

@ -321,7 +321,7 @@ void Foam::controlMeshRefinement::initialMeshPopulation
sizes.clear();
alignments.clear();
PackedBoolList keepVertex(vertices.size(), true);
bitSet keepVertex(vertices.size(), true);
forAll(vertices, vI)
{
@ -496,7 +496,7 @@ void Foam::controlMeshRefinement::initialMeshPopulation
}
}
PackedBoolList keepVertex(vertices.size(), true);
bitSet keepVertex(vertices.size(), true);
forAll(vertices, vI)
{

View File

@ -1081,7 +1081,7 @@ void Foam::conformalVoronoiMesh::move()
Zero
);
PackedBoolList pointToBeRetained(number_of_vertices(), true);
bitSet pointToBeRetained(number_of_vertices(), true);
DynamicList<Point> pointsToInsert(number_of_vertices());

View File

@ -47,7 +47,7 @@ SourceFiles
#include "cellShapeControl.H"
#include "cvControls.H"
#include "DynamicList.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "Time.H"
#include "polyMesh.H"
#include "plane.H"
@ -606,7 +606,7 @@ private:
pointField& cellCentres,
labelList& cellToDelaunayVertex,
labelListList& patchToDelaunayVertex,
PackedBoolList& boundaryFacesToRemove
bitSet& boundaryFacesToRemove
);
void calcNeighbourCellCentres
@ -760,7 +760,7 @@ private:
wordList& patchNames,
PtrList<dictionary>& patchDicts,
labelListList& patchPointPairSlaves,
PackedBoolList& boundaryFacesToRemove,
bitSet& boundaryFacesToRemove,
bool includeEmptyPatches = false
) const;
@ -791,7 +791,7 @@ private:
faceList& faces,
labelList& owner,
PtrList<dictionary>& patchDicts,
PackedBoolList& boundaryFacesToRemove,
bitSet& boundaryFacesToRemove,
const List<DynamicList<face>>& patchFaces,
const List<DynamicList<label>>& patchOwners,
const List<DynamicList<bool>>& indirectPatchFace
@ -997,7 +997,7 @@ public:
const wordList& patchNames,
const PtrList<dictionary>& patchDicts,
const pointField& cellCentres,
PackedBoolList& boundaryFacesToRemove
bitSet& boundaryFacesToRemove
) const;
//- Calculate and write a field of the target cell size,

View File

@ -47,7 +47,7 @@ void Foam::conformalVoronoiMesh::calcDualMesh
pointField& cellCentres,
labelList& cellToDelaunayVertex,
labelListList& patchToDelaunayVertex,
PackedBoolList& boundaryFacesToRemove
bitSet& boundaryFacesToRemove
)
{
timeCheck("Start calcDualMesh");
@ -277,7 +277,7 @@ void Foam::conformalVoronoiMesh::calcTetMesh
sortFaces(faces, owner, neighbour);
// PackedBoolList boundaryFacesToRemove;
// bitSet boundaryFacesToRemove;
// List<DynamicList<bool>> indirectPatchFace;
//
// addPatches
@ -703,7 +703,7 @@ Foam::conformalVoronoiMesh::createPolyMeshFromPoints
PtrList<dictionary> patchDicts;
pointField cellCentres;
labelListList patchToDelaunayVertex;
PackedBoolList boundaryFacesToRemove;
bitSet boundaryFacesToRemove;
timeCheck("Start of checkPolyMeshQuality");
@ -1103,7 +1103,7 @@ Foam::labelHashSet Foam::conformalVoronoiMesh::checkPolyMeshQuality
}
PackedBoolList ptToBeLimited(pts.size(), false);
bitSet ptToBeLimited(pts.size(), false);
forAllConstIter(labelHashSet, wrongFaces, iter)
{
@ -1704,7 +1704,7 @@ void Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
wordList& patchNames,
PtrList<dictionary>& patchDicts,
labelListList& patchPointPairSlaves,
PackedBoolList& boundaryFacesToRemove,
bitSet& boundaryFacesToRemove,
bool includeEmptyPatches
) const
{
@ -2486,7 +2486,7 @@ void Foam::conformalVoronoiMesh::addPatches
faceList& faces,
labelList& owner,
PtrList<dictionary>& patchDicts,
PackedBoolList& boundaryFacesToRemove,
bitSet& boundaryFacesToRemove,
const List<DynamicList<face>>& patchFaces,
const List<DynamicList<label>>& patchOwners,
const List<DynamicList<bool>>& indirectPatchFace
@ -2531,7 +2531,7 @@ void Foam::conformalVoronoiMesh::removeUnusedPoints
{
Info<< nl << "Removing unused points" << endl;
PackedBoolList ptUsed(pts.size(), false);
bitSet ptUsed(pts.size(), false);
// Scan all faces to find all of the points that are used
@ -2585,7 +2585,7 @@ Foam::labelList Foam::conformalVoronoiMesh::removeUnusedCells
{
Info<< nl << "Removing unused cells" << endl;
PackedBoolList cellUsed(vertexCount(), false);
bitSet cellUsed(vertexCount(), false);
// Scan all faces to find all of the cells that are used

View File

@ -2271,7 +2271,7 @@ void Foam::conformalVoronoiMesh::reinsertSurfaceConformation()
ptPairs_.reIndex(oldToNewIndices);
PackedBoolList selectedElems(surfaceConformationVertices_.size(), true);
bitSet selectedElems(surfaceConformationVertices_.size(), true);
forAll(surfaceConformationVertices_, vI)
{
@ -2295,7 +2295,7 @@ void Foam::conformalVoronoiMesh::reinsertSurfaceConformation()
}
}
inplaceSubset<PackedBoolList, List<Vb>>
inplaceSubset<bitSet, List<Vb>>
(
selectedElems,
surfaceConformationVertices_

View File

@ -115,7 +115,7 @@ void Foam::conformalVoronoiMesh::writeMesh(const fileName& instance)
wordList patchNames;
PtrList<dictionary> patchDicts;
pointField cellCentres;
PackedBoolList boundaryFacesToRemove;
bitSet boundaryFacesToRemove;
calcDualMesh
(
@ -377,7 +377,7 @@ void Foam::conformalVoronoiMesh::writeMesh(const fileName& instance)
//
// Info<< nl << "Writing tetDualMesh to " << instance << endl;
//
// PackedBoolList boundaryFacesToRemove;
// bitSet boundaryFacesToRemove;
// writeMesh
// (
// "tetDualMesh",
@ -773,7 +773,7 @@ void Foam::conformalVoronoiMesh::writeMesh
const wordList& patchNames,
const PtrList<dictionary>& patchDicts,
const pointField& cellCentres,
PackedBoolList& boundaryFacesToRemove
bitSet& boundaryFacesToRemove
) const
{
if (foamyHexMeshControls().objOutput())
@ -949,7 +949,7 @@ void Foam::conformalVoronoiMesh::writeMesh
orEqOp<unsigned int>()
);
labelList addr(boundaryFacesToRemove.used());
labelList addr(boundaryFacesToRemove.toc());
faceSet indirectPatchFaces
(

View File

@ -496,7 +496,7 @@ void Foam::CV2D::newPoints()
scalar u = 1.0;
scalar l = 0.7;
PackedBoolList pointToBeRetained(startOfSurfacePointPairs_, true);
bitSet pointToBeRetained(startOfSurfacePointPairs_, true);
std::list<Point> pointsToInsert;

View File

@ -122,7 +122,7 @@ SourceFiles
#include "point2DFieldFwd.H"
#include "dictionary.H"
#include "Switch.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "EdgeMap.H"
#include "cv2DControls.H"
#include "tolerances.H"

View File

@ -306,7 +306,7 @@ void Foam::mergeAndWrite
// Determine faces on outside of cellSet
PackedBoolList isInSet(mesh.nCells());
bitSet isInSet(mesh.nCells());
forAllConstIter(cellSet, set, iter)
{
isInSet.set(iter.key());

View File

@ -660,7 +660,7 @@ Foam::label Foam::checkTopology
const cellList& cells = mesh.cells();
const faceList& faces = mesh.faces();
PackedBoolList isZonePoint(mesh.nPoints());
bitSet isZonePoint(mesh.nPoints());
for (const cellZone& cZone : cellZones)
{

View File

@ -192,7 +192,7 @@ void modifyOrAddFace
const label zoneID,
const bool zoneFlip,
PackedBoolList& modifiedFace
bitSet& modifiedFace
)
{
if (modifiedFace.set(facei))
@ -247,7 +247,7 @@ void createFaces
const labelList& newMasterPatches,
const labelList& newSlavePatches,
polyTopoChange& meshMod,
PackedBoolList& modifiedFace,
bitSet& modifiedFace,
label& nModified
)
{
@ -538,15 +538,13 @@ int main(int argc, char *argv[])
if (mesh.faceZones().findZoneID(name) == -1)
{
mesh.faceZones().clearAddressing();
label sz = mesh.faceZones().size();
const label zoneID = mesh.faceZones().size();
labelList addr(0);
boolList flip(0);
mesh.faceZones().setSize(sz+1);
mesh.faceZones().setSize(zoneID+1);
mesh.faceZones().set
(
sz,
new faceZone(name, addr, flip, sz, mesh.faceZones())
zoneID,
new faceZone(name, labelList(), false, zoneID, mesh.faceZones())
);
}
}
@ -604,7 +602,14 @@ int main(int argc, char *argv[])
mesh.faceZones().set
(
zoneID,
new faceZone(name, addr, flip, zoneID, mesh.faceZones())
new faceZone
(
name,
std::move(addr),
std::move(flip),
zoneID,
mesh.faceZones()
)
);
}
@ -751,7 +756,7 @@ int main(int argc, char *argv[])
// side come first and faces from the other side next.
// Whether first use of face (modify) or consecutive (add)
PackedBoolList modifiedFace(mesh.nFaces());
bitSet modifiedFace(mesh.nFaces());
label nModified = 0;
forAll(selectors, selectorI)

View File

@ -483,7 +483,7 @@ int main(int argc, char *argv[])
}
candidates.setCapacity(sz);
PackedBoolList isCandidate(mesh.nPoints());
bitSet isCandidate(mesh.nPoints());
forAll(splitPatchIDs, i)
{
const labelList& mp = patches[splitPatchIDs[i]].meshPoints();

View File

@ -87,7 +87,7 @@ int main(int argc, char *argv[])
const PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh));
const bitSet isMasterFace(syncTools::getMasterFaces(mesh));
// Data on all edges and faces

View File

@ -146,7 +146,7 @@ Foam::label Foam::meshDualiser::findDualCell
void Foam::meshDualiser::generateDualBoundaryEdges
(
const PackedBoolList& isBoundaryEdge,
const bitSet& isBoundaryEdge,
const label pointi,
polyTopoChange& meshMod
)
@ -374,7 +374,7 @@ Foam::label Foam::meshDualiser::addBoundaryFace
void Foam::meshDualiser::createFacesAroundEdge
(
const bool splitFace,
const PackedBoolList& isBoundaryEdge,
const bitSet& isBoundaryEdge,
const label edgeI,
const label startFacei,
polyTopoChange& meshMod,
@ -886,7 +886,7 @@ void Foam::meshDualiser::setRefinement
// Mark boundary edges and points.
// (Note: in 1.4.2 we can use the built-in mesh point ordering
// facility instead)
PackedBoolList isBoundaryEdge(mesh_.nEdges());
bitSet isBoundaryEdge(mesh_.nEdges());
for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); facei++)
{
const labelList& fEdges = mesh_.faceEdges()[facei];

View File

@ -48,7 +48,7 @@ SourceFiles
#define meshDualiser_H
#include "DynamicList.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "boolList.H"
#include "typeInfo.H"
@ -100,7 +100,7 @@ class meshDualiser
// emanating from (boundary & feature) point
void generateDualBoundaryEdges
(
const PackedBoolList& isBoundaryEdge,
const bitSet& isBoundaryEdge,
const label pointi,
polyTopoChange& meshMod
);
@ -143,7 +143,7 @@ class meshDualiser
void createFacesAroundEdge
(
const bool splitFace,
const PackedBoolList& isBoundaryEdge,
const bitSet& isBoundaryEdge,
const label edgeI,
const label startFacei,
polyTopoChange& meshMod,

View File

@ -67,7 +67,7 @@ Note
#include "unitConversion.H"
#include "polyTopoChange.H"
#include "mapPolyMesh.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "meshTools.H"
#include "OFstream.H"
#include "meshDualiser.H"
@ -87,7 +87,7 @@ using namespace Foam;
void simpleMarkFeatures
(
const polyMesh& mesh,
const PackedBoolList& isBoundaryEdge,
const bitSet& isBoundaryEdge,
const scalar featureAngle,
const bool concaveMultiCells,
const bool doNotPreserveFaceZones,
@ -390,7 +390,7 @@ int main(int argc, char *argv[])
// Mark boundary edges and points.
// (Note: in 1.4.2 we can use the built-in mesh point ordering
// facility instead)
PackedBoolList isBoundaryEdge(mesh.nEdges());
bitSet isBoundaryEdge(mesh.nEdges());
for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); facei++)
{
const labelList& fEdges = mesh.faceEdges()[facei];

View File

@ -79,7 +79,7 @@ void printEdgeStats(const polyMesh& mesh)
scalar minOther = GREAT;
scalar maxOther = -GREAT;
PackedBoolList isMasterEdge(syncTools::getMasterEdges(mesh));
bitSet isMasterEdge(syncTools::getMasterEdges(mesh));
const edgeList& edges = mesh.edges();

View File

@ -303,7 +303,7 @@ void subsetTopoSets
Info<< "Subsetting " << set.type() << " " << set.name() << endl;
// Map the data
PackedBoolList isSet(set.maxSize(mesh));
bitSet isSet(set.maxSize(mesh));
forAllConstIters(set, iter)
{
isSet.set(iter.key());

View File

@ -32,7 +32,7 @@ Description
#include "domainDecomposition.H"
#include "IOstreams.H"
#include "boolList.H"
#include "bitSet.H"
#include "cyclicPolyPatch.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -434,7 +434,6 @@ void Foam::domainDecomposition::decomposeMesh()
// }
Info<< "\nDistributing points to processors" << endl;
// For every processor, loop through the list of faces for the processor.
// For every face, loop through the list of points and mark the point as
@ -443,42 +442,19 @@ void Foam::domainDecomposition::decomposeMesh()
forAll(procPointAddressing_, proci)
{
boolList pointLabels(nPoints(), false);
bitSet pointsInUse(nPoints(), false);
// Get reference to list of used faces
const labelList& procFaceLabels = procFaceAddressing_[proci];
forAll(procFaceLabels, facei)
// For each of the faces used
for (const label facei : procFaceAddressing_[proci])
{
// Because of the turning index, some labels may be negative
const labelList& facePoints = fcs[mag(procFaceLabels[facei]) - 1];
// Because of the turning index, some face labels may be -ve
const labelList& facePoints = fcs[mag(facei) - 1];
forAll(facePoints, pointi)
{
// Mark the point as used
pointLabels[facePoints[pointi]] = true;
}
// Mark the face points as being used
pointsInUse.setMany(facePoints);
}
// Collect the used points
labelList& procPointLabels = procPointAddressing_[proci];
procPointLabels.setSize(pointLabels.size());
label nUsedPoints = 0;
forAll(pointLabels, pointi)
{
if (pointLabels[pointi])
{
procPointLabels[nUsedPoints] = pointi;
nUsedPoints++;
}
}
// Reset the size of used points
procPointLabels.setSize(nUsedPoints);
procPointAddressing_[proci] = pointsInUse.sortedToc();
}
}

View File

@ -41,7 +41,7 @@ Usage
#include "triSurfaceMesh.H"
#include "indexedOctree.H"
#include "treeBoundBox.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "unitConversion.H"
#include "searchableSurfaces.H"
#include "IOdictionary.H"
@ -329,7 +329,7 @@ int main(int argc, char *argv[])
List<DynamicList<labelledTri>> newFaces(surfs.size());
List<DynamicList<point>> newPoints(surfs.size());
List<PackedBoolList> visitedFace(surfs.size());
List<bitSet> visitedFace(surfs.size());
PtrList<triSurfaceMesh> newSurfaces(surfs.size());
forAll(surfs, surfI)
@ -370,7 +370,7 @@ int main(int argc, char *argv[])
newFaces[surfI] = newSurf.localFaces();
newPoints[surfI] = newSurf.localPoints();
visitedFace[surfI] = PackedBoolList(newSurf.size(), false);
visitedFace[surfI] = bitSet(newSurf.size(), false);
}
forAll(newSurfaces, surfI)

View File

@ -54,7 +54,7 @@ Usage
#include "triSurfaceFields.H"
#include "triSurfaceMesh.H"
#include "triSurfaceGeoMesh.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "OBJstream.H"
#include "surfaceFeatures.H"
@ -131,7 +131,7 @@ tmp<vectorField> calcVertexNormals(const triSurface& surf)
tmp<vectorField> calcPointNormals
(
const triSurface& s,
const PackedBoolList& isFeaturePoint,
const bitSet& isFeaturePoint,
const List<surfaceFeatures::edgeStatus>& edgeStat
)
{
@ -215,7 +215,7 @@ tmp<vectorField> calcPointNormals
void detectSelfIntersections
(
const triSurfaceMesh& s,
PackedBoolList& isEdgeIntersecting
bitSet& isEdgeIntersecting
)
{
const edgeList& edges = s.edges();
@ -258,9 +258,9 @@ label detectIntersectionPoints
const vectorField& displacement,
const bool checkSelfIntersect,
const PackedBoolList& initialIsEdgeIntersecting,
const bitSet& initialIsEdgeIntersecting,
PackedBoolList& isPointOnHitEdge,
bitSet& isPointOnHitEdge,
scalarField& scale
)
{
@ -307,7 +307,7 @@ label detectIntersectionPoints
// 2. (new) surface self intersections
if (checkSelfIntersect)
{
PackedBoolList isEdgeIntersecting;
bitSet isEdgeIntersecting;
detectSelfIntersections(s, isEdgeIntersecting);
const edgeList& edges = s.edges();
@ -400,7 +400,7 @@ tmp<scalarField> avg
void minSmooth
(
const triSurface& s,
const PackedBoolList& isAffectedPoint,
const bitSet& isAffectedPoint,
const scalarField& fld,
scalarField& newFld
)
@ -442,19 +442,19 @@ void lloydsSmoothing
(
const label nSmooth,
triSurface& s,
const PackedBoolList& isFeaturePoint,
const bitSet& isFeaturePoint,
const List<surfaceFeatures::edgeStatus>& edgeStat,
const PackedBoolList& isAffectedPoint
const bitSet& isAffectedPoint
)
{
const labelList& meshPoints = s.meshPoints();
const edgeList& edges = s.edges();
PackedBoolList isSmoothPoint(isAffectedPoint);
bitSet isSmoothPoint(isAffectedPoint);
// Extend isSmoothPoint
{
PackedBoolList newIsSmoothPoint(isSmoothPoint);
bitSet newIsSmoothPoint(isSmoothPoint);
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
@ -539,7 +539,7 @@ void lloydsSmoothing
// Extend isSmoothPoint
{
PackedBoolList newIsSmoothPoint(isSmoothPoint);
bitSet newIsSmoothPoint(isSmoothPoint);
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
@ -662,7 +662,7 @@ int main(int argc, char *argv[])
<< " out of " << s.nEdges() << nl
<< endl;
PackedBoolList isFeaturePoint(s.nPoints(), features.featurePoints());
bitSet isFeaturePoint(s.nPoints(), features.featurePoints());
const List<surfaceFeatures::edgeStatus> edgeStat(features.toStatus());
@ -723,11 +723,11 @@ int main(int argc, char *argv[])
// Any point on any intersected edge in any of the iterations
PackedBoolList isScaledPoint(s.nPoints());
bitSet isScaledPoint(s.nPoints());
// Detect any self intersections on initial mesh
PackedBoolList initialIsEdgeIntersecting;
bitSet initialIsEdgeIntersecting;
if (checkSelfIntersect)
{
detectSelfIntersections(s, initialIsEdgeIntersecting);
@ -775,7 +775,7 @@ int main(int argc, char *argv[])
// Detect any intersections and scale back
PackedBoolList isAffectedPoint;
bitSet isAffectedPoint;
label nIntersections = detectIntersectionPoints
(
1e-9, // intersection tolerance
@ -818,7 +818,7 @@ int main(int argc, char *argv[])
minSmooth
(
s,
PackedBoolList(s.nPoints(), true),
bitSet(s.nPoints(), true),
oldScale,
scale
);

View File

@ -54,7 +54,7 @@ using namespace Foam;
tmp<pointField> avg
(
const meshedSurface& s,
const PackedBoolList& fixedPoints
const bitSet& fixedPoints
)
{
const labelListList& pointEdges = s.pointEdges();
@ -95,7 +95,7 @@ void getFixedPoints
(
const edgeMesh& feMesh,
const pointField& points,
PackedBoolList& fixedPoints
bitSet& fixedPoints
)
{
scalarList matchDistance(feMesh.points().size(), 1e-1);
@ -177,7 +177,7 @@ int main(int argc, char *argv[])
<< "Vertices : " << surf1.nPoints() << nl
<< "Bounding Box: " << boundBox(surf1.localPoints()) << endl;
PackedBoolList fixedPoints(surf1.localPoints().size(), false);
bitSet fixedPoints(surf1.localPoints().size(), false);
if (args.found("featureFile"))
{

View File

@ -390,6 +390,7 @@ DebugSwitches
basicMixture 0;
basicReactingCloud 0;
basicReactingParcel 0;
bitSet 0;
fluidThermo 0;
fluidThermoCloud 0;
fluidThermoParcel 0;

View File

@ -145,11 +145,12 @@ primitives/polynomialEqns/quadraticEqn/quadraticEqn.C
primitives/Barycentric/barycentric/barycentric.C
primitives/Barycentric2D/barycentric2D/barycentric2D.C
containers/Bits/bitSet/bitSet.C
containers/Bits/bitSet/bitSetIO.C
containers/Bits/PackedList/PackedListCore.C
containers/HashTables/HashOps/HashOps.C
containers/HashTables/HashTable/HashTableCore.C
containers/Lists/SortableList/ParSortableListName.C
containers/Lists/PackedList/PackedListCore.C
containers/Lists/PackedList/PackedBoolList.C
containers/Lists/ListOps/ListOps.C
containers/LinkedLists/linkTypes/SLListBase/SLListBase.C
containers/LinkedLists/linkTypes/DLListBase/DLListBase.C

View File

@ -0,0 +1,192 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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/>.
Namespace
Foam::BitOps
Description
Various bit-wise operations, etc.
The population count uses the Hamming weight
(http://en.wikipedia.org/wiki/Hamming_weight).
\*---------------------------------------------------------------------------*/
#ifndef BitOps_H
#define BitOps_H
#include "label.H"
#include "Ostream.H"
#include <limits>
#include <utility>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Namespace BitOps Declaration
\*---------------------------------------------------------------------------*/
namespace BitOps
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Count arbitrary number of bits (of an integral type)
template<class UIntType>
inline unsigned int bit_count(UIntType x)
{
unsigned int n = 0u;
for (; x; ++n) { x &= (x-1); }
return n;
}
//- Count bits in a 32-bit value (Hamming weight method)
template<>
inline unsigned int bit_count(uint32_t x)
{
x -= (x >> 1) & 0x55555555;
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
return ((((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
}
//- Count bits in a 64-bit value (Hamming weight method)
template<>
inline unsigned int bit_count(uint64_t x)
{
x -= (x >> 1) & 0x5555555555555555;
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
return unsigned
((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101) >> 56);
}
//- Repeat a value of the given BitWidth into the destination output type.
template<class UIntType, unsigned BitWidth>
inline UIntType repeat_value(unsigned val)
{
static_assert
(
BitWidth && std::numeric_limits<UIntType>::digits >= BitWidth,
"BitWidth too large for target output"
);
// How many fit into the target
const unsigned nrepeat = (std::numeric_limits<UIntType>::digits / BitWidth);
// Max value for a single element
const unsigned mask = ((1u << BitWidth) - 1);
// The first occurance
UIntType fillval = ((val >= mask) ? mask : val);
// Repeated
for (unsigned i = 1; i < nrepeat; ++i)
{
fillval |= (fillval << BitWidth);
}
return fillval;
}
//- Print 0/1 bits in the (unsigned) integral type
template<class UIntType>
inline Ostream& print(Ostream& os, UIntType value, char off='0', char on='1')
{
if (os.format() == IOstream::BINARY)
{
// Perhaps not the most sensible, but the only thing we currently have.
os << label(value);
}
else
{
// Starting from most significant bit - makes for easy reading.
for
(
unsigned test = (1u << (std::numeric_limits<UIntType>::digits-1));
test;
test >>= 1u
)
{
os << ((value & test) ? on : off);
}
}
return os;
}
//- An (unsigned) integral type adapter, for output of bit values
template<class UIntType>
struct bitInfo
{
typedef UIntType value_type;
value_type value;
//- Null constructible as zero
bitInfo() : value(0) {}
//- Value construct
explicit bitInfo(UIntType val) : value(val) {}
//- Conversion to base type
operator UIntType () const { return value; }
//- Conversion to base type
operator UIntType& () { return value; }
};
} // End namespace BitOps
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Print 0/1 bits of an (unsigned) integral type via an adapter
template<class UIntType>
inline Ostream& operator<<(Ostream& os, const BitOps::bitInfo<UIntType>& info)
{
BitOps::print(os, info.value);
return os;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 "PackedList.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<unsigned Width>
bool Foam::PackedList<Width>::uniform() const
{
if (size() < 2)
{
return false; // Trivial case
}
// The value of the first element for testing
const unsigned int val = get(0);
const label nblocks = num_blocks(size());
bool identical = true;
if (!val)
{
// Zero value: can just check block content directly
for (label blocki = 0; identical && blocki < nblocks; ++blocki)
{
identical = !blocks_[blocki];
}
return identical;
}
else if (nblocks > 1)
{
// Check all blocks that are completely occupied: (nblocks-1)
const unsigned int blockval =
BitOps::repeat_value<block_type,Width>(val);
for (label blocki = 0; identical && blocki < (nblocks-1); ++blocki)
{
identical = (blocks_[blocki] == blockval);
}
}
// Partial block: check manually
for
(
label elemi = elem_per_block*(nblocks-1);
identical && elemi < size();
++elemi
)
{
identical = (val == get(elemi));
}
return identical;
}
template<unsigned Width>
Foam::labelList Foam::PackedList<Width>::values() const
{
if (size() < 2 || uniform())
{
const label val = (size() ? get(0) : 0);
return labelList(size(), val);
}
labelList output(size());
label outi = 0;
// Process n-1 complete blocks
const label nblocks = num_blocks(size());
for (label blocki=0; blocki < nblocks-1; ++blocki)
{
unsigned int blockval = blocks_[blocki];
for (unsigned nget = elem_per_block; nget; --nget, ++outi)
{
output[outi] = label(blockval & max_value);
blockval >>= Width;
}
}
// Any partial blocks
for (/*nil*/; outi < size(); ++outi)
{
output[outi] = get(outi);
}
return output;
}
// ************************************************************************* //

View File

@ -25,11 +25,11 @@ Class
Foam::PackedList
Description
A dynamically list of packed unsigned integers, with the number of bits
per item specified by the \<nBits\> template parameter.
A dynamic list of packed unsigned integers, with the number of bits
per item specified by the \<Width\> template parameter.
Resizing is similar to DynamicList so that clear() and resize() affect
the addessed size, but not the allocated size. The reserve() and
the addressed size, but not the allocated size. The reserve() and
setCapacity() methods can be used to influence the allocation.
Note
@ -37,13 +37,20 @@ Note
with out-of-range elements returned as zero.
In a non-const context, the '[]' operator returns a reference to an
existing value. Some caution with out-of-range elements to ensure
that the const version of the [] operator is being called.
The get() method is functionally identical to the '[]' operator, but
existing value. When accessing out-of-range elements, some caution
is required to ensure that the const version of the [] operator is actually
being called.
The get() method is functionally identical the the '[]' operator, but
is always const access.
The set() and unset() methods return a bool if the value changed.
This can be useful for branching on changed values.
With const access, the get() method and 'operator[]' are identical.
With non-const access, the 'operator[]' may be marginally slower get().
The set() method may be marginally faster than using the 'operator[]'
supports auto-vivification and also returns a bool if the value changed,
which can be useful for branching on changed values.
\code
list.set(5, 4);
@ -56,27 +63,38 @@ Note
For example,
\code
list.resize(4);
Info<< list.get(10) << "\n"; // print zero, but doesn't adjust list
Info<< list.get(10) << "\n"; // print zero, but doesn't adjust list
list.set(8); // auto-vivify
\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.
Note
Iterators for this class have been intentionally removed, for performance
reasons.
See also
Foam::BitOps
Foam::DynamicList
SourceFiles
PackedListI.H
PackedList.C
PackedListIO.C
\*---------------------------------------------------------------------------*/
#ifndef PackedList_H
#define PackedList_H
#include "BitOps.H"
#include "labelList.H"
#include "UIndirectList.H"
#include "InfoProxy.H"
#include "PackedListCore.H"
#include <type_traits>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -85,51 +103,102 @@ namespace Foam
{
// Forward declarations
template<unsigned nBits> class PackedList;
template<unsigned Width> class PackedList;
class Istream;
class Ostream;
template<unsigned nBits>
Istream& operator>>(Istream& is, PackedList<nBits>& lst);
template<unsigned nBits>
Ostream& operator<<(Ostream& os, const PackedList<nBits>& lst);
template<unsigned Width>
Istream& operator>>(Istream& is, PackedList<Width>& list);
template<unsigned Width>
Ostream& operator<<(Ostream& os, const PackedList<Width>& list);
/*---------------------------------------------------------------------------*\
Class PackedListCore Declaration
\*---------------------------------------------------------------------------*/
//- Template-invariant bits for PackedList
struct PackedListCore
{
//- Construct null
PackedListCore()
{}
//- Define template name and debug
ClassName("PackedList");
};
template<unsigned Width>
Ostream& operator<<(Ostream& os, const InfoProxy<PackedList<Width>>& info);
/*---------------------------------------------------------------------------*\
Class PackedList Declaration
\*---------------------------------------------------------------------------*/
template<unsigned nBits=1>
template<unsigned Width>
class PackedList
:
public PackedListCore,
private List<unsigned int>
public Detail::PackedListCore
{
public:
// Types and dimension information
//- The storage block type for bit elements
typedef unsigned int block_type;
//- The number of bits in a single block
static constexpr unsigned bits_per_block
= (std::numeric_limits<block_type>::digits);
//- The width of an individual element (in bits).
static constexpr unsigned element_width = (Width);
//- The number of elements stored per data block.
static constexpr unsigned elem_per_block = (bits_per_block / Width);
//- The max value for an element which is also the bit-mask of the
//- individual element.
// Eg, for Width=2: ((1 << 2) - 1) == 0b0011
static constexpr block_type max_value = ((1u << Width) - 1);
//- Calculate the number of blocks required to _address_ the
//- requested number of elements.
//
// We calculate this:
// \code
// (numElem / elem_per_block)
// + (numElem % elem_per_block) ? 1 : 0
// \code
// But avoiding the modulus operation
static constexpr label num_blocks(label numElem)
{
return ((numElem - 1 + elem_per_block) / elem_per_block);
}
//- Masking for all bits below the element offset.
// Ill-defined when elementOffset is out of range.
static constexpr block_type mask_lower(unsigned elementOffset)
{
return (~0u >> (bits_per_block - Width * elementOffset));
}
protected:
typedef unsigned int StorageType;
typedef List<StorageType> StorageList;
// Protected Data
//- The internal container for storing the blocks
typedef List<block_type> block_container;
//- The blocks of raw data
block_container blocks_;
//- Number of entries used
label size_;
//- Enforce non-zero Width to fit within the block storage and require
//- at least 2 items per storage block for general efficiency.
//
// Thus 1/2 of the base storage size is (sizeof(block_type)*8/2),
// or (sizeof(block_type) << 2)
static_assert
(
Width && Width <= (sizeof(block_type) << 2),
"Width must be > 0 and minimum of two items per data block"
);
// Protected Member Functions
//- Calculate the list length when packed
inline static constexpr label packedLength(const label nElem);
//- A fill value for complete blocks
inline static unsigned int repeated_value(unsigned val);
//- Read a list entry (allows for specialization)
inline static unsigned int readValue(Istream& is);
@ -138,33 +207,13 @@ protected:
// For bool specialization, read a single index value
inline void setPair(Istream& is);
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.
static_assert
(
nBits && nBits <= (sizeof(StorageType) << 2),
"nBits must be positive (non-zero) and fit within the storage"
);
// Private data
//- Number of nBits entries
label size_;
protected:
// Protected Member Functions
//- Write as a dictionary entry
void writeEntry(Ostream& os) const;
//- Clear any partial rubbish in the last addressable block
// This \a rubbish may have arisen from block-wise operations etc.
inline void clear_trailing_bits();
public:
@ -174,129 +223,93 @@ public:
typedef unsigned int const_reference;
// Public data
//- The max. number of bits that can be templated.
// Might someday be useful for a template assert.
inline static constexpr unsigned int max_bits();
//- The max. value for an entry, which simultaneously the bit-mask
// eg, ((1 << 2) - 1) yields 0b0011
inline static constexpr unsigned int max_value();
//- The number of entries per packed storage element
inline static constexpr unsigned int packing();
//- Masking for all bits below the offset
inline static constexpr unsigned int maskLower(unsigned offset);
// Constructors
//- Null constructor
inline PackedList();
inline constexpr PackedList() noexcept;
//- Construct with given size, initializes list to 0
explicit inline PackedList(const label size);
//- Construct for given number of elements, initializes values to 0
explicit inline PackedList(const label numElem);
//- Construct with given size and value for all elements
inline PackedList(const label size, const unsigned val);
//- Construct for given number of elements, and the specified
//- value for each element
inline PackedList(const label numElem, const unsigned int val);
//- Construct from Istream
inline PackedList(Istream& is);
//- Copy construct
inline PackedList(const PackedList<nBits>& lst);
inline PackedList(const PackedList<Width>& rhs);
//- Move construct
inline PackedList(PackedList<nBits>&& lst);
inline PackedList(PackedList<Width>&& rhs);
//- Construct from a list of labels
explicit inline PackedList(const labelUList& lst);
//- Construct from a list of values
explicit inline PackedList(const labelUList& values);
//- Construct from an indirect list of labels
explicit inline PackedList(const labelUIndList& lst);
//- Construct from a list of values
explicit inline PackedList(const labelUIndList& values);
//- Clone
inline autoPtr<PackedList<nBits>> clone() const;
inline autoPtr<PackedList<Width>> clone() const;
// Member Functions
// Access
//- The number of elements that can be stored before reallocating
inline label capacity() const;
//- Number of entries.
inline label size() const;
//- Return true if the list is empty (ie, size() is zero).
inline bool empty() const;
//- Get value at index I.
// Never auto-vivify entries.
inline unsigned int get(const label i) const;
//- Set value at index I, default value set is the max_value.
// Does auto-vivify for non-existent, non-zero entries.
// \return true if value changed.
inline bool set(const label i, const unsigned int val = ~0u);
//- Unset the entry at index I.
// Never auto-vivify entries.
// \return true if value changed.
inline bool unset(const label i);
//- Return the underlying packed storage
// Manipulate with utmost caution
inline List<unsigned int>& storage();
//- Return the underlying packed storage
inline const List<unsigned int>& storage() const;
//- The list length when packed
inline label packedLength() const;
//- The number of bytes used in the underlying storage
inline std::streamsize byteSize() const;
//- Count number of bits set, O(log(n))
// Uses the Hamming weight (population count) method
// http://en.wikipedia.org/wiki/Hamming_weight
unsigned int count() const;
//- Return the values as a list of labels
labelList values() const;
//- Print bit patterns, optionally output unused elements
//
// addressable bits:
// on: '1', off: '-'
//
// non-addressable bits:
// on: '!', off: '.'
//
Ostream& printBits(Ostream& os, const bool fullOutput=false) const;
//- Print information and bit patterns (with printBits)
Ostream& printInfo(Ostream& os, const bool fullOutput=false) const;
// Check
// Query
//- Check index is within valid range [0,size)
inline void checkIndex(const label i) const;
//- Number of entries.
inline label size() const noexcept;
//- Return true if the list is empty (ie, size() is zero).
inline bool empty() const noexcept;
//- The number of elements that can be stored with reallocating
inline label capacity() const;
//- True if there are two or more entries and all entries have
//- identical values.
bool uniform() const;
// Access
//- Get value at index i or 0 for out-of-range.
// Never auto-vivify entries.
inline unsigned int get(const label i) const;
//- Set value at index i, default value set is the max_value.
// Does auto-vivify for non-existent, non-zero entries.
// \return true if value changed.
inline bool set(const label i, unsigned int val = ~0u);
//- Unset the entry at index i.
// Never auto-vivify entries.
// \return true if the value changed.
inline bool unset(const label i);
//- Return the values as a list of labels
labelList values() const;
// Edit
//- Trim any trailing zero elements
bool trim();
//- Assign all entries to the given value. Takes linear time.
inline void assign(const unsigned int val);
//- Invert the bits in the addressable region
void flip();
//- Copy assignment.
inline void assign(const PackedList<Width>& rhs);
//- Clear all bits
//- Trim any trailing zero elements, optionally specifying a
//- a minimum position, below which trimming will not occur.
//
// \return true if trimming changed the size.
inline bool trim(label minpos=-1);
//- Clear all bits but do not adjust the addressable size.
inline void reset();
//- Alter the size of the underlying storage.
@ -327,13 +340,36 @@ public:
//- Shrink the allocated space to what is actually used.
inline void shrink();
//- Swap contents with argument
inline void swap(PackedList<Width>& rhs);
//- Transfer the contents of the argument list into this list
// and annul the argument list.
inline void transfer(PackedList<nBits>& lst);
inline void transfer(PackedList<Width>& rhs);
// Low-level access
//- The number of bytes used in the underlying storage
//- including any unused padding.
inline std::streamsize byteSize() const;
//- The number of internal storage blocks
inline label nBlocks() const;
//- Return the underlying storage blocks
inline const List<unsigned int>& storage() const;
//- Return the underlying storage blocks
// Manipulate with utmost caution
inline List<unsigned int>& storage();
// IO
//- Print bit patterns, optionally with extra debug
Ostream& printBits(Ostream& os, bool debugOutput=false) const;
//- Clear list and read from stream
Istream& read(Istream& is);
@ -349,7 +385,7 @@ public:
// Member Operators
//- Append a value at the end of the list
inline PackedList<nBits>& append(const unsigned int val);
inline PackedList<Width>& append(const unsigned int val);
//- Remove and return the last element
inline unsigned int remove();
@ -366,32 +402,30 @@ public:
inline void operator=(const unsigned int val);
//- Copy assignment.
void operator=(const PackedList<nBits>& lst);
inline void operator=(const PackedList<Width>& lst);
//- Move assignment.
void operator=(PackedList<nBits>&& lst);
//- Assignment operator.
void operator=(const labelUList& lst);
//- Assignment operator.
void operator=(const labelUIndList& lst);
inline void operator=(PackedList<Width>&& lst);
// Iterators and helpers
// Access helpers
//- A reference for read/write access to an entry
//- A reference supporting read/write access to an entry
class reference
{
friend class PackedList; // Access for PackedList
protected:
friend class PackedList; // Access for parent
void operator&() = delete; // Refuse to provide its address
unsigned int& ref_; //!< Reference to underlying block value
unsigned int shift_; //!< The bit shift for the sub-portion
//- Reference to the block
block_type& ref_;
//- Construct by taking reference of block from within the list
//- at the specified index.
inline reference(PackedList* lst, const label index);
//- The bit shift to access the given sub-portion
unsigned shift_;
//- Construct by taking reference of block from within
//- the list and the specified index.
inline reference(PackedList* parent, const label index);
//- Get value as unsigned, no range-checking
inline unsigned int get() const;
@ -404,27 +438,40 @@ public:
//- Value assignment
inline void operator=(const reference& other);
//- Value assignment
//- Value assignment.
inline void operator=(const unsigned int val);
//- Conversion operator
//- Conversion operator.
inline operator unsigned int () const;
};
// IOstream Operators
friend Istream& operator>> <nBits>
(
Istream& is,
PackedList<nBits>& lst
);
//- Return info proxy.
InfoProxy<PackedList<Width>> info() const
{
return *this;
}
friend Ostream& operator<< <nBits>
friend Ostream& operator<< <Width>
(
Ostream& os,
const PackedList<nBits>& lst
const InfoProxy<PackedList<Width>>& info
);
friend Istream& operator>> <Width>
(
Istream& is,
PackedList<Width>& list
);
friend Ostream& operator<< <Width>
(
Ostream& os,
const PackedList<Width>& list
);
};
@ -440,6 +487,7 @@ public:
#ifdef NoRepository
#include "PackedList.C"
#include "PackedListIO.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -23,14 +23,16 @@ License
\*---------------------------------------------------------------------------*/
#include "PackedList.H"
#include "PackedListCore.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(PackedListCore, 0);
namespace Detail
{
defineTypeName(PackedListCore);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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::Detail::PackedListCore
Description
Implementation of template-invariant details for Foam::PackedList
SourceFiles
PackedListCore.C
\*---------------------------------------------------------------------------*/
#ifndef PackedListCore_H
#define PackedListCore_H
#include "className.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace Detail
{
/*---------------------------------------------------------------------------*\
Class Detail::PackedListCore Declaration
\*---------------------------------------------------------------------------*/
//- Template-invariant parts for PackedList
struct PackedListCore
{
//- Define template name
ClassNameNoDebug("PackedList");
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Detail
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,753 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "error.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<unsigned Width>
inline unsigned int Foam::PackedList<Width>::repeated_value(unsigned val)
{
std::cout << "call repeated_value" << nl;
return BitOps::repeat_value<block_type,Width>(val);
}
template<unsigned Width>
inline unsigned int Foam::PackedList<Width>::readValue(Istream& is)
{
const unsigned int val = readLabel(is);
if (val > max_value)
{
FatalIOErrorInFunction(is)
<< "Out-of-range value " << val << " for PackedList<" << Width
<< ">. Maximum permitted value is " << max_value << "."
<< exit(FatalIOError);
}
return val;
}
template<unsigned Width>
inline void Foam::PackedList<Width>::setPair(Istream& is)
{
is.readBegin("Tuple2<label,uint32>");
const label ind = readLabel(is);
const unsigned int val = readLabel(is);
is.readEnd("Tuple2<label,uint32>");
if (val > max_value)
{
FatalIOErrorInFunction(is)
<< "Out-of-range value " << val << " for PackedList<" << Width
<< "> at index " << ind
<< ". Maximum permitted value is " << max_value << "."
<< exit(FatalIOError);
}
set(ind, val);
is.check(FUNCTION_NAME);
}
template<unsigned Width>
inline void Foam::PackedList<Width>::clear_trailing_bits()
{
// Mask off any partial rubbish in final block
const unsigned int blk = size() / elem_per_block;
const unsigned int off = size() % elem_per_block;
if (off)
{
blocks_[blk] &= mask_lower(off);
}
}
template<unsigned Width>
inline bool Foam::PackedList<Width>::trim(label minpos)
{
if (empty())
{
return false; // Trivial case
}
const label orig = size();
if (orig < minpos)
{
minpos = orig; // Don't allow allow accidental growth!
}
for (label blocki = num_blocks(size())-1; blocki >= 0; --blocki)
{
// Truncate to the block begin
size_ = blocki * elem_per_block;
unsigned int blockval = blocks_[blocki];
// Some bits were found in the block, increment size again
if (blockval)
{
for (; blockval; ++size_)
{
blockval >>= Width;
}
break;
}
else if (size_ < minpos)
{
break;
}
}
if (size_ < minpos)
{
size_ = minpos;
}
return (size() != orig);
}
// * * * * * * * * * * * * * * * Specializations * * * * * * * * * * * * * * //
namespace Foam
{
template<> inline unsigned int PackedList<1>::repeated_value(unsigned val)
{
return (val ? ~0u : 0u);
}
template<> inline unsigned int PackedList<1>::readValue(Istream& is)
{
return readBool(is);
}
template<> inline void PackedList<1>::setPair(Istream& is)
{
set(readLabel(is), true);
}
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<unsigned Width>
inline constexpr Foam::PackedList<Width>::PackedList() noexcept
:
blocks_(),
size_(0)
{}
template<unsigned Width>
inline Foam::PackedList<Width>::PackedList(const label numElem)
:
blocks_(num_blocks(numElem), 0u),
size_(numElem)
{}
template<unsigned Width>
inline Foam::PackedList<Width>::PackedList
(
const label numElem,
const unsigned int val
)
:
blocks_(num_blocks(numElem), 0u),
size_(numElem)
{
if (val)
{
operator=(val);
}
}
template<unsigned Width>
inline Foam::PackedList<Width>::PackedList(Istream& is)
:
blocks_(),
size_(0)
{
read(is);
}
template<unsigned Width>
inline Foam::PackedList<Width>::PackedList(const PackedList<Width>& rhs)
:
blocks_(rhs.blocks_),
size_(rhs.size_)
{}
template<unsigned Width>
inline Foam::PackedList<Width>::PackedList(PackedList<Width>&& rhs)
:
blocks_(std::move(rhs.blocks_)),
size_(rhs.size_)
{
rhs.size_ = 0;
}
template<unsigned Width>
inline Foam::PackedList<Width>::PackedList(const labelUList& values)
:
blocks_(num_blocks(values.size()), 0u),
size_(values.size())
{
const label len = values.size();
// Could add more intelligent filling (blockwise), but likely done
// fairly infrequently
for (label i = 0; i < len; ++i)
{
const unsigned int val(values[i]);
if (val) set(i, val);
}
}
template<unsigned Width>
inline Foam::PackedList<Width>::PackedList(const labelUIndList& values)
:
blocks_(num_blocks(values.size()), 0u),
size_(values.size())
{
const label len = values.size();
// Could add more intelligent filling (blockwise), but likely done
// fairly infrequently
for (label i = 0; i < len; ++i)
{
const unsigned int val(values[i]);
if (val) set(i, val);
}
}
template<unsigned Width>
inline Foam::autoPtr<Foam::PackedList<Width>>
Foam::PackedList<Width>::clone() const
{
return autoPtr<PackedList<Width>>::New(*this);
}
// * * * * * * * * * * * * * * * * References * * * * * * * * * * * * * * * * //
template<unsigned Width>
inline Foam::PackedList<Width>::reference::reference
(
PackedList<Width>* parent,
const label index
)
:
ref_(parent->blocks_[index / elem_per_block]),
shift_(Width * (index % elem_per_block))
{}
template<unsigned Width>
inline unsigned int Foam::PackedList<Width>::reference::get() const
{
return ((ref_ >> shift_) & max_value);
}
template<unsigned Width>
inline bool Foam::PackedList<Width>::reference::set(const unsigned int val)
{
const unsigned int mask = (max_value << shift_);
const unsigned int prev = ref_;
if (val >= max_value)
{
ref_ |= mask; // Overflow is max_value, so fill entirely
}
else
{
ref_ &= ~mask;
ref_ |= mask & (val << shift_);
}
return (prev != ref_);
}
template<unsigned Width>
inline void Foam::PackedList<Width>::reference::operator=
(
const reference& other
)
{
this->set(other.get());
}
template<unsigned Width>
inline void Foam::PackedList<Width>::reference::operator=
(
const unsigned int val
)
{
this->set(val);
}
template<unsigned Width>
inline Foam::PackedList<Width>::reference::operator unsigned int () const
{
return this->get();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<unsigned Width>
inline void Foam::PackedList<Width>::checkIndex(const label i) const
{
if (!size_)
{
FatalErrorInFunction
<< "attempt to access element " << i << " from zero sized list"
<< abort(FatalError);
}
else if (i < 0 || i >= size_)
{
FatalErrorInFunction
<< "index " << i << " out of range [0," << size_ << ")"
<< abort(FatalError);
}
}
template<unsigned Width>
inline Foam::label Foam::PackedList<Width>::size() const noexcept
{
return size_;
}
template<unsigned Width>
inline bool Foam::PackedList<Width>::empty() const noexcept
{
return !size_;
}
template<unsigned Width>
inline Foam::label Foam::PackedList<Width>::capacity() const
{
return elem_per_block * blocks_.size();
}
template<unsigned Width>
inline void Foam::PackedList<Width>::resize
(
const label newSize,
const unsigned int val
)
{
reserve(newSize);
const label oldSize = size();
size_ = newSize;
if (oldSize < size())
{
// Fill new elements or newly exposed elements
if (val)
{
// Fill value for complete blocks
const unsigned int blockval = repeated_value(val);
// Fill complete blocks
const label oldLen = num_blocks(oldSize);
const label newLen = num_blocks(size());
for (label blocki = oldLen; blocki < newLen; ++blocki)
{
blocks_[blocki] = blockval;
}
// Finish previous partial block, preserve existing value
{
const unsigned int blk = oldSize / elem_per_block;
const unsigned int off = oldSize % elem_per_block;
if (off)
{
const unsigned int mask = mask_lower(off);
blocks_[blk] &= mask;
blocks_[blk] |= ~mask & blockval;
}
}
clear_trailing_bits();
}
}
else if (size() < oldSize)
{
// The list is now shorter than before, so we zero assign the unused
// blocks and any trailing junk. This costs slightly here, but make
// things much simpler elsewhere.
// Clear complete blocks
const label oldLen = num_blocks(oldSize);
const label newLen = num_blocks(size());
for (label blocki = newLen; blocki < oldLen; ++blocki)
{
blocks_[blocki] = 0u;
}
clear_trailing_bits();
}
}
template<unsigned Width>
inline void Foam::PackedList<Width>::setSize
(
const label newSize,
const unsigned int val
)
{
resize(newSize, val);
}
template<unsigned Width>
inline void Foam::PackedList<Width>::setCapacity(const label numElem)
{
const label nblocks = num_blocks(numElem);
blocks_.resize(nblocks, 0u);
if (numElem < size())
{
size_ = numElem;
clear_trailing_bits();
}
}
template<unsigned Width>
inline void Foam::PackedList<Width>::reserve(const label numElem)
{
const label oldLen = blocks_.size();
const label newLen = num_blocks(numElem);
// Allocate more capacity if necessary
if (oldLen < newLen)
{
blocks_.resize
(
// SizeMin=16, allocation doubling
max(16, max(newLen, 2*oldLen)),
0u
);
}
}
template<unsigned Width>
inline void Foam::PackedList<Width>::reset()
{
blocks_ = 0u;
}
template<unsigned Width>
inline void Foam::PackedList<Width>::clear()
{
reset();
size_ = 0;
}
template<unsigned Width>
inline void Foam::PackedList<Width>::clearStorage()
{
blocks_.clear();
size_ = 0;
}
template<unsigned Width>
inline void Foam::PackedList<Width>::shrink()
{
// Any unneeded space allocated?
const label nblocks = num_blocks(size());
if (nblocks < blocks_.size())
{
blocks_.resize(nblocks);
}
}
template<unsigned Width>
inline Foam::List<unsigned int>& Foam::PackedList<Width>::storage()
{
return blocks_;
}
template<unsigned Width>
inline const Foam::List<unsigned int>& Foam::PackedList<Width>::storage() const
{
return blocks_;
}
template<unsigned Width>
inline Foam::label Foam::PackedList<Width>::nBlocks() const
{
return num_blocks(size());
}
template<unsigned Width>
inline std::streamsize Foam::PackedList<Width>::byteSize() const
{
return num_blocks(size()) * sizeof(block_type);
}
template<unsigned Width>
inline void Foam::PackedList<Width>::swap(PackedList<Width>& rhs)
{
blocks_.swap(rhs.blocks_);
Foam::Swap(size_, rhs.size_);
}
template<unsigned Width>
inline void Foam::PackedList<Width>::transfer(PackedList<Width>& rhs)
{
blocks_.transfer(rhs.blocks_);
size_ = rhs.size_;
rhs.size_ = 0;
}
template<unsigned Width>
inline unsigned int Foam::PackedList<Width>::get(const label i) const
{
if (i < 0 || i >= size())
{
#ifdef FULLDEBUG
if (i < 0)
{
WarningInFunction
<< "Ignoring attempt to get a negative index " << i
<< " range is [0," << size_ << ")"
<< endl;
}
#endif
// Lazy evaluation - return 0 for out-of-range
return 0u;
}
return reference(const_cast<PackedList<Width>*>(this), i).get();
}
template<unsigned Width>
inline bool Foam::PackedList<Width>::set
(
const label i,
const unsigned int val
)
{
if (i < 0)
{
#ifdef FULLDEBUG
WarningInFunction
<< "Ignoring attempt to set a negative index " << i
<< " range is [0," << size_ << ")"
<< endl;
}
#endif
// Lazy evaluation - ignore out-of-bounds
return false;
}
else if (i >= size())
{
if (!val)
{
// Same as unset out-of-bounds = noop
return false;
}
// Lazy evaluation - increase size on assigment
resize(i + 1);
}
return reference(this, i).set(val);
}
template<unsigned Width>
inline bool Foam::PackedList<Width>::unset(const label i)
{
if (i < 0 || i >= size())
{
// Unset out-of-bounds = noop
return false;
}
return reference(this, i).set(0u);
}
template<unsigned Width>
inline Foam::PackedList<Width>&
Foam::PackedList<Width>::append(const unsigned int val)
{
const label idx = size();
reserve(idx + 1);
++size_;
reference(this, idx).set(val);
return *this;
}
template<unsigned Width>
inline unsigned int Foam::PackedList<Width>::remove()
{
// Location of last element and simultaneously the new size
const label idx = size()-1;
if (idx < 0)
{
FatalErrorInFunction
<< "List is empty" << abort(FatalError);
}
const unsigned int old = reference(this, idx).get();
resize(idx);
return old;
}
template<unsigned Width>
inline void Foam::PackedList<Width>::assign(const unsigned int val)
{
const label nblocks = num_blocks(size());
// Trivial cases first
if (!nblocks)
{
return;
}
else if (!val)
{
for (label blocki=0; blocki < nblocks; ++blocki)
{
blocks_[blocki] = 0u;
}
return;
}
// Fill value for complete blocks
const unsigned int blockval = repeated_value(val);
for (label blocki=0; blocki < nblocks; ++blocki)
{
blocks_[blocki] = blockval;
}
clear_trailing_bits();
}
template<unsigned Width>
inline void Foam::PackedList<Width>::assign(const PackedList<Width>& list)
{
blocks_ = list.blocks_;
size_ = list.size_;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<unsigned Width>
inline unsigned int Foam::PackedList<Width>::operator[](const label i) const
{
return get(i);
}
template<unsigned Width>
inline typename Foam::PackedList<Width>::reference
Foam::PackedList<Width>::operator[](const label i)
{
// Leave enabled during testing period (MAR-2018)
// #ifdef FULLDEBUG
checkIndex(i);
// #endif
return reference(this, i);
}
template<unsigned Width>
inline void Foam::PackedList<Width>::operator=(const unsigned int val)
{
assign(val);
}
template<unsigned Width>
inline void Foam::PackedList<Width>::operator=(const PackedList<Width>& rhs)
{
assign(rhs);
}
template<unsigned Width>
inline void Foam::PackedList<Width>::operator=(PackedList<Width>&& rhs)
{
transfer(rhs);
}
// ************************************************************************* //

View File

@ -0,0 +1,314 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 "PackedList.H"
#include "IOstreams.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<unsigned Width>
void Foam::PackedList<Width>::writeEntry(Ostream& os) const
{
os << *this;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<unsigned Width>
Foam::Ostream& Foam::PackedList<Width>::printBits
(
Ostream& os,
bool debugOutput
) const
{
os << token::BEGIN_LIST << nl;
const label nblocks = debugOutput ? blocks_.size() : num_blocks(size());
for (label blocki = 0; blocki < nblocks; ++blocki)
{
BitOps::print(os, blocks_[blocki], '.') << nl;
}
os << token::END_LIST << nl;
return os;
}
template<unsigned Width>
Foam::Istream& Foam::PackedList<Width>::read(Istream& is)
{
PackedList<Width>& list = *this;
list.clear();
is.fatalCheck(FUNCTION_NAME);
token firstTok(is);
is.fatalCheck
(
"PackedList::read(Istream&) : "
"reading first token"
);
if (firstTok.isLabel())
{
const label len = firstTok.labelToken();
// Set list length to that read
list.resize(len);
// Read list contents depending on data format
if (is.format() == IOstream::ASCII)
{
// Read beginning of contents
const char delimiter = is.readBeginList("PackedList");
if (len)
{
if (delimiter == token::BEGIN_LIST)
{
for (label i=0; i<len; ++i)
{
list[i] = list.readValue(is);
is.fatalCheck
(
"PackedList::read(Istream&) : "
"reading entry"
);
}
}
else if (delimiter == token::BEGIN_BLOCK)
{
// Assign for all entries
list = list.readValue(is);
is.fatalCheck
(
"PackedList::read(Istream&) : "
"reading the single entry"
);
}
else
{
FatalIOErrorInFunction(is)
<< "incorrect list token, expected '(' or '{', found "
<< firstTok.info()
<< exit(FatalIOError);
}
}
// Read end of contents
is.readEndList("PackedList");
}
else
{
if (len)
{
is.read
(
reinterpret_cast<char*>(list.storage().data()),
list.byteSize()
);
is.fatalCheck
(
"PackedList::read(Istream&) : "
"reading the binary block"
);
}
}
}
else if (firstTok.isPunctuation())
{
if (firstTok.pToken() == token::BEGIN_LIST)
{
token nextTok(is);
is.fatalCheck(FUNCTION_NAME);
while
(
!( nextTok.isPunctuation()
&& nextTok.pToken() == token::END_LIST
)
)
{
is.putBack(nextTok);
list.append(list.readValue(is));
is >> nextTok;
is.fatalCheck(FUNCTION_NAME);
}
}
else if (firstTok.pToken() == token::BEGIN_BLOCK)
{
token nextTok(is);
is.fatalCheck(FUNCTION_NAME);
while
(
!( nextTok.isPunctuation()
&& nextTok.pToken() == token::END_BLOCK
)
)
{
is.putBack(nextTok);
list.setPair(is);
is >> nextTok;
is.fatalCheck(FUNCTION_NAME);
}
}
else
{
FatalIOErrorInFunction(is)
<< "incorrect first token, expected '(', found "
<< firstTok.info()
<< exit(FatalIOError);
}
}
else
{
FatalIOErrorInFunction(is)
<< "incorrect first token, expected <int>, '(' or '{', found "
<< firstTok.info()
<< exit(FatalIOError);
}
return is;
}
template<unsigned Width>
Foam::Ostream& Foam::PackedList<Width>::writeList
(
Ostream& os,
const label shortListLen
) const
{
const PackedList<Width>& list = *this;
const label len = list.size();
// Write list contents depending on data format
if (os.format() == IOstream::ASCII)
{
if (list.uniform())
{
// Two or more entries, and all entries have identical values.
os << len << token::BEGIN_BLOCK << list[0] << token::END_BLOCK;
}
else if (!shortListLen || len <= shortListLen)
{
// Shorter list, or line-breaks suppressed
os << len << token::BEGIN_LIST;
for (label i=0; i < len; ++i)
{
if (i) os << token::SPACE;
os << list[i];
}
os << token::END_LIST;
}
else
{
// Longer list
os << nl << len << nl << token::BEGIN_LIST << nl;
for (label i=0; i < len; ++i)
{
os << list[i] << nl;
}
os << token::END_LIST << nl;
}
}
else
{
// Contents are binary and contiguous
os << nl << len << nl;
if (len)
{
// write(...) includes surrounding start/end delimiters
os.write
(
reinterpret_cast<const char*>(list.storage().cdata()),
list.byteSize()
);
}
}
return os;
}
template<unsigned Width>
void Foam::PackedList<Width>::writeEntry
(
const word& keyword,
Ostream& os
) const
{
os.writeKeyword(keyword);
writeEntry(os);
os << token::END_STATEMENT << endl;
}
// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
template<unsigned Width>
Foam::Istream& Foam::operator>>(Istream& is, PackedList<Width>& list)
{
return list.read(is);
}
template<unsigned Width>
Foam::Ostream& Foam::operator<<(Ostream& os, const PackedList<Width>& list)
{
return list.writeList(os, 10);
}
template<unsigned Width>
Foam::Ostream& Foam::operator<<
(
Ostream& os,
const InfoProxy<PackedList<Width>>& iproxy
)
{
const PackedList<Width>& list = iproxy.t_;
os << "PackedList<" << Width
<< "> size=" << list.size() << "/" << list.capacity()
<< " (limits: max=" << PackedList<Width>::max_value
<< ", elem_per_block=" << PackedList<Width>::elem_per_block
<< ")"
<< nl;
return os;
}
// ************************************************************************* //

View File

@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, licensed under GNU General Public License
<http://www.gnu.org/licenses/>.
Typedef
Foam::PackedBoolList
Description
Compatibility name. Superseded (MAR-2018) by Foam::bitSet
\*---------------------------------------------------------------------------*/
#ifndef PackedBoolList_H
#define PackedBoolList_H
#include "bitSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef bitSet PackedBoolList;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,569 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 "bitSet.H"
#include "labelRange.H"
#include "IOstreams.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(bitSet, 0);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::bitSet& Foam::bitSet::minusEq(const bitSet& other)
{
if (&other == this)
{
// Self '-=' : results in clearing all bits
if (debug & 2)
{
InfoInFunction
<< "Perform -= on self: clears all bits" << nl;
}
reset();
return *this;
}
else if (empty() || other.empty())
{
return *this;
}
// The operation (on overlapping blocks)
{
const label nblocks = num_blocks(std::min(size(), other.size()));
const auto& rhs = other.blocks_;
for (label blocki = 0; blocki < nblocks; ++blocki)
{
blocks_[blocki] &= ~rhs[blocki];
}
}
return *this;
}
Foam::bitSet& Foam::bitSet::andEq(const bitSet& other)
{
if (&other == this)
{
// Self '&=' : no-op
if (debug & 2)
{
InfoInFunction
<< "Perform &= on self: ignore" << nl;
}
return *this;
}
else if (empty())
{
// empty set : no-op (no overlap possible)
return *this;
}
else if (other.empty())
{
reset(); // Other is empty - no overlap possible
return *this;
}
// The operation (on overlapping blocks)
{
const label nblocks = num_blocks(std::min(size(), other.size()));
const auto& rhs = other.blocks_;
for (label blocki = 0; blocki < nblocks; ++blocki)
{
blocks_[blocki] &= rhs[blocki];
}
}
return *this;
}
Foam::bitSet& Foam::bitSet::orEq(const bitSet& other, const bool strict)
{
if (&other == this)
{
// Self '|=' : no-op
if (debug & 2)
{
InfoInFunction
<< "Perform |= on self: ignore" << nl;
}
return *this;
}
else if (other.empty())
{
if ((debug & 2) && !empty())
{
// OK if both are empty
InfoInFunction
<< "Perform |= using empty operand: ignore" << nl;
}
// No (normal) overlap: no-op
return *this;
}
else if (empty())
{
if (debug & 2)
{
InfoInFunction
<< "Perform |= on empty bitSet" << nl;
}
if (strict)
{
// No (normal) overlap: no-op
return *this;
}
}
else if ((debug & 2) && (size() != other.size()))
{
InfoInFunction
<< "Perform |= on dissimilar sized bitSets: "
<< size() << " vs. " << other.size() << nl;
}
{
return *this;
}
label minpos = -1; // Min trim point
if ((size() < other.size()) && !strict)
{
// The size (B > A) and we are non-strict (greedy), which means we may
// acquire additional bits from B. However, we would like to avoid
// spurious changes in the size of A (ie, B is longer but the extra
// bits are unset and thus don't affect the logical result).
minpos = size();
resize(other.size()); // Blocks now overlap
}
// The operation (on overlapping blocks)
{
const label nblocks = num_blocks(std::min(size(), other.size()));
const auto& rhs = other.blocks_;
for (label blocki = 0; blocki < nblocks; ++blocki)
{
blocks_[blocki] |= rhs[blocki];
}
}
// Cleanup - minpos >= 0 means we need to check/adjust the trim point
if (minpos >= 0)
{
trim(minpos); // Adjust the trim point (size)
}
else
{
clear_trailing_bits();
}
return *this;
}
Foam::bitSet& Foam::bitSet::xorEq(const bitSet& other, const bool strict)
{
if (&other == this)
{
// Self '^=' : results in clearing all bits
if (debug & 2)
{
InfoInFunction
<< "Perform ^= on self: clears all bits" << nl;
}
reset();
return *this;
}
else if (other.empty())
{
if ((debug & 2) && !empty())
{
// OK if both are empty
InfoInFunction
<< "Perform ^= using empty operand: ignore" << nl;
}
// No (normal) overlap: no-op
return *this;
}
else if (empty())
{
if (debug & 2)
{
InfoInFunction
<< "Perform ^= on empty bitSet" << nl;
}
if (strict)
{
// No (normal) overlap: no-op
return *this;
}
}
else if ((debug & 2) && (size() != other.size()))
{
InfoInFunction
<< "Perform ^= on dissimilar sized bitSets: "
<< size() << " vs. " << other.size() << nl;
}
label minpos = -1; // Min trim point
if ((size() < other.size()) && !strict)
{
minpos = size(); // This logic is explained in the orEq() method
resize(other.size()); // Blocks now overlap
}
// The operation (on overlapping blocks)
{
const label nblocks = num_blocks(std::min(size(), other.size()));
const auto& rhs = other.blocks_;
for (label blocki = 0; blocki < nblocks; ++blocki)
{
blocks_[blocki] ^= rhs[blocki];
}
}
// Cleanup - minpos >= 0 means we need to check/adjust the trim point
if (minpos >= 0)
{
trim(minpos); // Adjust the trim point (size)
}
else
{
clear_trailing_bits();
}
return *this;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::bitSet::bitSet(Istream& is)
:
PackedList<1>()
{
is >> *this;
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::bitSet::assign(const UList<bool>& bools)
{
const label len = bools.size();
resize(len);
assign(false);
// Could also handle block-wise (in the future?)
// Set according to indices that are true.
for (label i = 0; i < len; ++i)
{
if (bools[i])
{
set(i);
}
}
}
bool Foam::bitSet::intersects(const bitSet& other) const
{
if (size() && other.size())
{
const label nblocks = num_blocks(std::min(size(), other.size()));
const auto& rhs = other.blocks_;
for (label blocki = 0; blocki < nblocks; ++blocki)
{
if (bool(blocks_[blocki] & rhs[blocki]))
{
return true;
}
}
}
return false;
}
void Foam::bitSet::set(const labelRange& range)
{
labelRange slice(range);
slice.adjust(); // No negative start, size adjusted accordingly
// Range is invalid (zero-sized or entirely negative) - noop
if (slice.empty())
{
return;
}
// Range finishes at or beyond the right side.
// - zero fill any gaps that we might create.
// - flood-fill the reset, which now correponds to the full range.
//
// NB: use labelRange after() for the exclusive end-value, which
// corresponds to our new set size.
if (slice.after() >= size())
{
resize(slice.start(), false);
resize(slice.after(), true);
return;
}
// The more difficult case - everything in between.
// 1. sequence may begin/end in the same block
// 2. Cover more than one block
// a. with partial coverage in the first block
// b. with partial coverage in the end block
// The begin block/offset
unsigned int bblock = slice.first() / elem_per_block;
unsigned int bmask = slice.first() % elem_per_block;
// The end block/offset
unsigned int eblock = slice.after() / elem_per_block;
unsigned int emask = slice.after() % elem_per_block;
// Transform offsets to lower bit masks
if (bmask) bmask = mask_lower(bmask);
if (emask) emask = mask_lower(emask);
if (bblock == eblock)
{
// Same block - flll between the begin/end bits.
// Example:
// bmask = 0000000000001111 (lower bits)
// emask = 0000111111111111 (lower bits)
// -> set 0000111111110000 (xor)
blocks_[bblock] |= (emask^bmask);
}
else
{
if (bmask)
{
// The first (partial) block
// - set everything above the bmask.
blocks_[bblock] |= (~bmask);
++bblock;
}
// Fill these blocks
for (unsigned blocki = bblock; blocki < eblock; ++blocki)
{
blocks_[blocki] = (~0u);
}
if (emask)
{
// The last (partial) block.
// - set everything below emask.
blocks_[eblock] |= (emask);
}
}
}
void Foam::bitSet::unset(const labelRange& range)
{
// Require intersection with the current bitset
const labelRange slice = range.subset0(size());
// Range does not intersect (invalid, empty, bitset is empty)
if (slice.empty())
{
return;
}
// Range finishes at or beyond the right side.
//
// NB: use labelRange after() for the exclusive end-value, which
// corresponds to our new set size.
if (slice.after() >= size())
{
// The original size
const label orig = size();
resize(slice.start(), false);
resize(orig, false);
return;
}
// The more difficult case - everything in between.
// 1. sequence may begin/end in the same block
// 2. Cover more than one block
// a. with partial coverage in the first block
// b. with partial coverage in the end block
// The begin block/offset
unsigned int bblock = slice.first() / elem_per_block;
unsigned int bmask = slice.first() % elem_per_block;
// The end block/offset
unsigned int eblock = slice.after() / elem_per_block;
unsigned int emask = slice.after() % elem_per_block;
// Transform offsets to lower bit masks
if (bmask) bmask = mask_lower(bmask);
if (emask) emask = mask_lower(emask);
if (bblock == eblock)
{
// Same block - flll between the begin/end bits.
// Example:
// bmask = 0000000000001111 (lower bits)
// emask = 0000111111111111 (lower bits)
// -> set 0000111111110000 (xor)
// -> ~ 1111000000001111
blocks_[bblock] &= (~(emask^bmask));
}
else
{
if (bmask)
{
// The first (partial) block
// - only retain things below bmask.
blocks_[bblock] &= (bmask);
++bblock;
}
// Clear these blocks
for (unsigned blocki = bblock; blocki < eblock; ++blocki)
{
blocks_[blocki] = (0u);
}
if (emask)
{
// The last (partial) block.
// - only retain things above bmask.
blocks_[eblock] &= (~emask);
}
}
}
Foam::labelList Foam::bitSet::toc() const
{
// Number of used (set) entries
const label total = any() ? count() : 0;
if (!total)
{
return labelList();
}
labelList output(total);
label nItem = 0;
// Process block-wise, detecting any '1' bits
const label nblocks = num_blocks(size());
for (label blocki = 0; blocki < nblocks; ++blocki)
{
unsigned int blockval = blocks_[blocki];
if (blockval)
{
for (label pos = (blocki * elem_per_block); blockval; ++pos)
{
if (blockval & 1u)
{
output[nItem] = pos;
++nItem;
}
blockval >>= 1u;
}
if (nItem == total) break; // Terminate early
}
}
return output;
}
Foam::List<bool> Foam::bitSet::values() const
{
List<bool> output(size(), false);
// Process block-wise, detecting any '1' bits
const label nblocks = num_blocks(size());
for (label blocki = 0; blocki < nblocks; ++blocki)
{
label pos = (blocki * elem_per_block);
for
(
unsigned int blockval = blocks_[blocki];
blockval;
blockval >>= 1u
)
{
if (blockval & 1u)
{
output[pos] = true;
}
++pos;
}
}
return output;
}
// ************************************************************************* //

View File

@ -0,0 +1,547 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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::bitSet
Description
A bitSet stores bits (elements with only two states) in packed internal
format and supports a variety of bit-set operations.
Its behaviour is largely list-like, with some HashSet features.
SourceFiles
bitSetI.H
bitSet.C
bitSetIO.C
bitSetTemplates.C
See also
Foam::BitOps
Foam::PackedList
\*---------------------------------------------------------------------------*/
#ifndef bitSet_H
#define bitSet_H
#include "className.H"
#include "PackedList.H"
#include "UIndirectList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declarations
class bitSet;
class labelRange;
/*---------------------------------------------------------------------------*\
Class bitSet Declaration
\*---------------------------------------------------------------------------*/
class bitSet
:
public PackedList<1>
{
protected:
// Protected Member Functions
//- Write as a dictionary entry
void writeEntry(Ostream& os) const;
// Logic/Set Operations
//- The set difference
// \code
// A = (A - B)
// A = (A & !B)
// A = (A & ~B)
// \endcode
// A and B can have different sizes.
// Does not change the original set size.
bitSet& minusEq(const bitSet& other);
//- The set logical AND
// \code
// A = (A & B)
//
// \endcode
// A and B can have different sizes..
// Does not change the original set size.
bitSet& andEq(const bitSet& other);
//- The set logical OR
// \code
// A = (A | B)
// \endcode
// A and B can have different sizes
//
// \note
// The default (strict=true) ignores additional length from B,
// whereas (strict=false) permits the set to automatically grow
// to accommodate additional elements arising from B.
bitSet& orEq(const bitSet& other, const bool strict=true);
//- The set logical XOR
// \code
// A = (A ^ B)
// \endcode
// A and B can have different sizes. Sizing behaviour as per orEq.
bitSet& xorEq(const bitSet& other, const bool strict=true);
public:
// Forward declaration of access classes
class reference;
class const_iterator;
typedef unsigned int const_reference;
//- Define class name and debug
ClassName("bitSet");
// Constructors
//- Construct an empty, zero-sized set
inline constexpr bitSet() noexcept;
//- Construct from Istream
explicit bitSet(Istream& is);
//- Construct with given size, with all bits set to 0
explicit inline bitSet(const label n);
//- Construct with given size and value for all elements
inline bitSet(const label n, const bool val);
//- Copy construct
inline bitSet(const bitSet& bitset);
//- Move construct
inline bitSet(bitSet&& bitset);
//- Construct from a list of bools
explicit inline bitSet(const UList<bool>& bools);
//- Construct with given size with all bits set to 0,
//- subsequently add specified locations as 1.
inline bitSet(const label n, const labelUList& locations);
//- Construct with given size with all bits set to 0,
//- subsequently add specified locations as 1.
inline bitSet(const label n, const labelUIndList& locations);
//- Construct with given size with all bits set to 0,
//- subsequently add specified locations as 1.
inline bitSet(const label n, std::initializer_list<label> locations);
//- Construct with automatic sizing (filled with 0),
//- and populate with specified locations as 1.
explicit inline bitSet(const labelUList& locations);
//- Construct with automatic sizing (filled with 0),
//- and populate with specified locations as 1.
explicit inline bitSet(const labelUIndList& locations);
//- Clone
inline autoPtr<bitSet> clone() const;
// Member Functions
// Query
//- True if all bits in this bitset are set or if the set is empty.
inline bool all() const;
//- True if any bits in this bitset are set.
inline bool any() const;
//- True if no bits in this bitset are set.
inline bool none() const;
//- True if there are two or more entries and all entries have
//- identical values.
inline bool uniform() const;
//- Count number of bits set.
inline unsigned int count() const;
//- True if any bits in the other bitset intersect (are the same).
//
// \note Method name compatibility with boost::dynamic_bitset
bool intersects(const bitSet& other) const;
//- Test value at specified position, never auto-vivify entries.
//
// \note Method name compatibility with std::bitset
inline bool test(const label pos) const;
//- Locate the first bit set.
// \return the location or -1 if there are no bits set.
//
// \note Method name compatibility with boost::dynamic_bitset
inline label find_first() const;
//- Locate the last bit set.
// \return the location or -1 if there are no bits set.
//
// \note Provided for symmetry with find_first()
inline label find_last() const;
//- Locate the next bit set, starting one beyond the specified position
// \return the location or -1 if there are no further bits set.
//
// \note Method name compatibility with boost::dynamic_bitset
inline label find_next(label pos) const;
//- The indices of the \a on bits as a sorted labelList.
//
// \note Method name compatibility with HashSet
labelList toc() const;
//- The indices of the \a on bits as a sorted labelList.
// This is identical to toc(), which is always sorted.
//
// \note Method name compatibility with HashSet
inline labelList sortedToc() const;
//- Return the bitset values as a boolList.
List<bool> values() const;
// Assignment
//- Assign all entries to the given value.
inline void assign(const bool val);
//- Copy assign all entries from a list of bools.
void assign(const UList<bool>& bools);
// Setting single or multiple values
//- Single index/value assign
using PackedList<1>::set;
//- Set specified bits from another bitset.
// The current set size may grow to accommodate any new bits
// (auto-vivifies).
inline void set(const bitSet& bitset);
//- Set the specified range of bits specified
// The current set size may grow to accommodate any new bits
// (auto-vivifies).
// \note this operation is generally more efficient than calling
// set(pos) on individual bits.
void set(const labelRange& range);
// Unsetting single or multiple values
//- Unset a single index
using PackedList<1>::unset;
//- Unset (subtract) the bits specified in the other bitset, which is
//- a set difference corresponds to the logical operation
// \code
// A = (A & !B)
// \endcode
// The result is comparable to 'operator-='
// \endcode
//
// A and B can have different sizes.
// Does not change the original set size.
inline bitSet& unset(const bitSet& other);
//- Unset the specified range of bits specified, never auto-vivifies.
// \note this operation can be more efficient than calling
// unset(pos) on individual bits.
void unset(const labelRange& range);
// Edit
//- Invert all bits in the addressable region
inline void flip();
//- Invert bits at the specified position.
// A no-op if the position is out-of-range
inline void flip(const label pos);
//- Swap contents
inline void swap(bitSet& bitset);
//- Transfer the contents of the argument list into this list
//- and annul the argument list.
inline void transfer(bitSet& bitset);
// Convenience methods
//- Ensure the addressable range does not exceed maxSize.
// Either decreases the size of the bitSet or is a no-op.
//
// \code
// pointField& pts = mesh.points();
// bitset.bound(pts.size());
//
// for (const label pointi : bitset)
// {
// pts[pointi] ...
// }
// \endcode
inline bitSet& bound(const label maxSize);
//- Ensure the addressable range does not exceed that of other.
// Either decreases the size of the bitSet or is a no-op.
inline bitSet& bound(const bitSet& other);
//- Ensure that minSize is covered by the bitSet.
// Either increases the size of the bitSet or is a no-op.
inline bitSet& extend(const label minSize);
//- Ensure the bitset is addressable throughout the range of other.
// Either increases the size of the bitSet or is a no-op.
inline bitSet& extend(const bitSet& other);
//- Set the listed locations to true.
// Does auto-vivify for non-existent entries.
inline void setMany(const labelUList& locations);
//- Set the listed locations to true.
// Does auto-vivify for non-existent entries.
inline void setMany(const labelUIndList& locations);
//- Set the locations listed by the iterator range,
// auto-vivify entries if needed.
template<class InputIter>
void setMany(InputIter first, InputIter last);
//- Unset the listed locations, never auto-vivifies.
inline void unsetMany(const labelUList& locations);
//- Unset the listed locations, never auto-vivifies.
inline void unsetMany(const labelUIndList& locations);
//- Unset the locations listed by the iterator range,
//- never auto-vivify entries.
template<class InputIter>
void unsetMany(InputIter first, InputIter last);
// Access helpers
//- A reference supporting read/write access to an entry
class reference
:
public PackedList<1>::reference
{
protected:
friend class bitSet; // Access for parent
void operator&() = delete; // Refuse to provide its address
//- Construct by taking reference of block from within
//- the list and the specified index.
inline reference(bitSet* parent, const label index);
public:
//- Flip the bit at the position, no range-checking
inline void flip();
//- Value assignment
inline void operator=(const reference& other);
//- Value assignment
inline void operator=(const unsigned int val);
//- Conversion operator
inline operator unsigned int () const;
};
// Iteration
//- A const_iterator for iterating across \a on values
class const_iterator
{
friend class bitSet;
//- The parent being iterated
const bitSet* set_;
//- Global position of the current \a on bit
label pos_;
//- Construct null - an end iterator
inline const_iterator() noexcept;
//- Construct begin iterator
inline const_iterator(const bitSet* bitset);
public:
//- Return the current \a on position
inline label operator*() const noexcept;
//- Move to the next \a on position
inline const_iterator& operator++();
inline bool operator==(const const_iterator& iter) const noexcept;
inline bool operator!=(const const_iterator& iter) const noexcept;
};
//- Iterator set to the position of the first \a on bit
inline const_iterator begin() const;
//- Iterator set to the position of the first \a on bit
inline const_iterator cbegin() const;
//- Iterator beyond the end of the bitSet
inline const_iterator end() const noexcept;
//- Iterator beyond the end of the bitSet
inline const_iterator cend() const noexcept;
// Member Operators
//- Identical to get() - get value at index.
// Never auto-vivify entries.
inline unsigned int operator[](const label i) const;
//- Non-const access to value at index.
// Fatal for out-of-range indices
inline reference operator[](const label i);
//- Assignment of all entries to the given value.
inline bitSet& operator=(const bool val);
//- Copy assignment
inline bitSet& operator=(const bitSet& bitset);
//- Move assignment
inline bitSet& operator=(bitSet&& bitset);
//- Complement operator.
// Return a copy of the existing set with all its bits flipped.
inline bitSet operator~() const;
//- Bitwise-AND all the bits in other with the bits in this bitset.
// The operands may have dissimilar sizes without affecting the size
// of the set.
inline bitSet& operator&=(const bitSet& other);
//- Bitwise-OR operator - similar to the set() method.
// The operands may have dissimilar sizes without affecting the size
// of the set.
inline bitSet& operator|=(const bitSet& other);
//- Bitwise-XOR operator - retains unique entries.
// The operands may have dissimilar sizes without affecting the size
// of the set.
inline bitSet& operator^=(const bitSet& other);
//- Remove entries from this list - identical to the unset() method.
// The operands may have dissimilar sizes without affecting the size
// of the set.
inline bitSet& operator-=(const bitSet& other);
// IO
//- Write the bitSet, with line-breaks in ASCII if the size
//- exceeds shortListLen.
// Using '0' suppresses line-breaks entirely.
Ostream& writeList(Ostream& os, const label shortListLen=0) const;
//- Write as a dictionary entry with keyword
void writeEntry(const word& keyword, Ostream& os) const;
// IOstream Operators
//- Return info proxy
InfoProxy<bitSet> info() const
{
return *this;
}
friend Ostream& operator<<
(
Ostream& os,
const InfoProxy<bitSet>& info
);
friend Ostream& operator<<
(
Ostream& os,
const bitSet& bitset
);
};
// Global Operators
//- Bitwise-AND of two bitsets.
// See bitSet::operator&= for more details.
inline bitSet operator&(const bitSet& a, const bitSet& b);
//- Bitwise-OR of two bitsets
// See bitSet::operator|= for more details.
inline bitSet operator|(const bitSet& a, const bitSet& b);
//- Bitwise-XOR of two bitsets to form a unique bit-set
// See bitSet::operator^= for more details.
inline bitSet operator^(const bitSet& a, const bitSet& b);
//- Bitwise difference (subset) of two bitsets to form a unique bit-set
// See bitSet::operator-= for more details.
inline bitSet operator-(const bitSet& a, const bitSet& b);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "bitSetI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "bitSetTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,672 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 constexpr Foam::bitSet::bitSet() noexcept
:
PackedList<1>()
{}
inline Foam::bitSet::bitSet(const label n)
:
PackedList<1>(n)
{}
inline Foam::bitSet::bitSet(const label n, const bool val)
:
bitSet(n)
{
if (val) assign(val);
}
inline Foam::bitSet::bitSet(const bitSet& bitset)
:
PackedList<1>(bitset)
{}
inline Foam::bitSet::bitSet(bitSet&& bitset)
:
PackedList<1>(std::move(bitset))
{}
inline Foam::bitSet::bitSet(const UList<bool>& bools)
:
bitSet()
{
assign(bools);
}
inline Foam::bitSet::bitSet(const label n, const labelUList& locations)
:
bitSet(n)
{
setMany(locations.begin(), locations.end());
}
inline Foam::bitSet::bitSet(const label n, const labelUIndList& locations)
:
bitSet(n)
{
setMany(locations.begin(), locations.end());
}
inline Foam::bitSet::bitSet
(
const label n,
std::initializer_list<label> locations
)
:
bitSet(n)
{
setMany(locations.begin(), locations.end());
}
inline Foam::bitSet::bitSet(const labelUList& locations)
:
bitSet()
{
setMany(locations.begin(), locations.end());
}
inline Foam::bitSet::bitSet(const labelUIndList& locations)
:
bitSet()
{
setMany(locations.begin(), locations.end());
}
inline Foam::autoPtr<Foam::bitSet> Foam::bitSet::clone() const
{
return autoPtr<bitSet>::New(*this);
}
// * * * * * * * * * * * * * * * * References * * * * * * * * * * * * * * * * //
inline Foam::bitSet::reference::reference
(
bitSet* parent,
const label index
)
:
PackedList<1>::reference(parent, index)
{}
inline void Foam::bitSet::reference::flip()
{
const unsigned int mask = (max_value << shift_);
ref_ ^= mask;
}
inline void Foam::bitSet::reference::operator=
(
const reference& other
)
{
set(other.get());
}
inline void Foam::bitSet::reference::operator=
(
const unsigned int val
)
{
set(val);
}
inline Foam::bitSet::reference::operator unsigned int () const
{
return get();
}
// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
inline Foam::bitSet::const_iterator::const_iterator() noexcept
:
set_(nullptr),
pos_(-1)
{}
inline Foam::bitSet::const_iterator::const_iterator(const bitSet* parent)
:
set_(parent),
pos_(set_->find_first())
{}
inline Foam::label Foam::bitSet::const_iterator::operator*() const noexcept
{
return pos_;
}
inline Foam::bitSet::const_iterator& Foam::bitSet::const_iterator::operator++()
{
pos_ = set_->find_next(pos_);
return *this;
}
inline bool Foam::bitSet::const_iterator::operator==
(
const const_iterator& iter
) const noexcept
{
return (iter.pos_ == pos_);
}
inline bool Foam::bitSet::const_iterator::operator!=
(
const const_iterator& iter
) const noexcept
{
return (iter.pos_ != pos_);
}
inline Foam::bitSet::const_iterator Foam::bitSet::begin() const
{
return const_iterator(this);
}
inline Foam::bitSet::const_iterator Foam::bitSet::cbegin() const
{
return const_iterator(this);
}
inline Foam::bitSet::const_iterator Foam::bitSet::end() const noexcept
{
return const_iterator();
}
inline Foam::bitSet::const_iterator Foam::bitSet::cend() const noexcept
{
return const_iterator();
}
inline Foam::label Foam::bitSet::find_first() const
{
// Process block-wise, detecting any '1' bits
const label nblocks = num_blocks(size());
for (label blocki = 0; blocki < nblocks; ++blocki)
{
label pos = (blocki * elem_per_block);
for
(
unsigned int blockval = blocks_[blocki];
blockval;
blockval >>= 1u
)
{
if (blockval & 1u)
{
return pos;
}
++pos;
}
}
return -1;
}
inline Foam::label Foam::bitSet::find_last() const
{
// Process block-wise, detecting any '1' bits
for (label blocki = num_blocks(size())-1; blocki >= 0; --blocki)
{
unsigned int blockval = blocks_[blocki];
if (blockval)
{
label pos = (blocki * elem_per_block) - 1;
while (blockval)
{
blockval >>= 1u;
++pos;
}
return pos;
}
}
return -1;
}
inline Foam::label Foam::bitSet::find_next(label pos) const
{
++pos;
if (pos < 0 || pos >= size())
{
return -1;
}
// The corresponding block/offset
label blocki = pos / elem_per_block;
unsigned int off = pos % elem_per_block;
for
(
unsigned int blockval = (blocks_[blocki] >> off);
blockval;
blockval >>= 1u
)
{
if (blockval & 1u)
{
return pos;
}
++pos;
}
// Normal block-wise search. Starting at the next block
const label nblocks = num_blocks(size());
for (++blocki; blocki < nblocks; ++blocki)
{
label pos = (blocki * elem_per_block);
for
(
unsigned int blockval = blocks_[blocki];
blockval;
blockval >>= 1u
)
{
if (blockval & 1u)
{
return pos;
}
++pos;
}
}
return -1;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::bitSet::all() const
{
if (empty())
{
return true;
}
// Use complement to change 0 <-> 1 and check if any 1's now appear
const label nblocks = num_blocks(size());
// Extra bits in the final block?
const unsigned int off = size() % elem_per_block;
if (!off)
{
for (label blocki=0; blocki < nblocks; ++blocki)
{
if (~(blocks_[blocki]))
{
return false;
}
}
}
else
{
for (label blocki=0; blocki < nblocks-1; ++blocki)
{
if (~(blocks_[blocki]))
{
return false;
}
}
// Verify the final block, with masking
return (!(~blocks_[nblocks-1] & mask_lower(off)));
}
return true;
}
inline bool Foam::bitSet::any() const
{
if (size())
{
const label nblocks = num_blocks(size());
for (label blocki=0; blocki < nblocks; ++blocki)
{
if (blocks_[blocki]) return true;
}
}
return false;
}
inline bool Foam::bitSet::none() const
{
return !any();
}
inline bool Foam::bitSet::uniform() const
{
return (size() > 1 && (test(0) ? all() : none()));
}
inline unsigned int Foam::bitSet::count() const
{
unsigned int total = 0;
const label nblocks = num_blocks(size());
for (label blocki = 0; blocki < nblocks; ++blocki)
{
total += BitOps::bit_count(blocks_[blocki]);
}
return total;
}
inline bool Foam::bitSet::test(const label pos) const
{
return get(pos);
}
inline Foam::labelList Foam::bitSet::sortedToc() const
{
return toc();
}
inline void Foam::bitSet::swap(bitSet& bitset)
{
PackedList<1>::swap(bitset);
}
inline void Foam::bitSet::transfer(bitSet& bitset)
{
PackedList<1>::transfer(bitset);
}
inline void Foam::bitSet::assign(const bool val)
{
if (empty())
{
return; // Trivial case
}
const label nblocks = num_blocks(size());
if (val)
{
for (label blocki=0; blocki < nblocks; ++blocki)
{
blocks_[blocki] = (~0u);
}
clear_trailing_bits();
}
else
{
for (label blocki=0; blocki < nblocks; ++blocki)
{
blocks_[blocki] = (0u);
}
}
}
inline void Foam::bitSet::set(const bitSet& bitset)
{
orEq(bitset, false); // Non-strict: Lets the set size grow.
}
inline void Foam::bitSet::setMany(const labelUList& locations)
{
setMany(locations.begin(), locations.end());
}
inline void Foam::bitSet::setMany(const labelUIndList& locations)
{
setMany(locations.begin(), locations.end());
}
inline void Foam::bitSet::unsetMany(const labelUList& locations)
{
unsetMany(locations.begin(), locations.end());
}
inline void Foam::bitSet::unsetMany(const labelUIndList& locations)
{
unsetMany(locations.begin(), locations.end());
}
inline Foam::bitSet& Foam::bitSet::unset(const bitSet& other)
{
return minusEq(other);
}
inline void Foam::bitSet::flip()
{
if (size())
{
const label nblocks = num_blocks(size());
for (label blocki=0; blocki < nblocks; ++blocki)
{
blocks_[blocki] = ~(blocks_[blocki]);
}
clear_trailing_bits();
}
}
inline void Foam::bitSet::flip(const label i)
{
if (i >= 0 && i < size())
{
reference(this, i).flip();
}
}
inline Foam::bitSet& Foam::bitSet::bound(const label maxSize)
{
if (maxSize < size())
{
resize(maxSize);
}
return *this;
}
inline Foam::bitSet& Foam::bitSet::bound(const bitSet& other)
{
return bound(other.size());
}
inline Foam::bitSet& Foam::bitSet::extend(const label minSize)
{
if (size() < minSize)
{
resize(minSize);
}
return *this;
}
inline Foam::bitSet& Foam::bitSet::extend(const bitSet& other)
{
return extend(other.size());
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline unsigned int Foam::bitSet::operator[](const label i) const
{
return get(i);
}
inline Foam::bitSet::reference Foam::bitSet::operator[](const label i)
{
// Leave enabled during testing period (MAR-2018) ... and perhaps later too
// #ifdef FULLDEBUG
checkIndex(i);
// #endif
return reference(this, i);
}
inline Foam::bitSet& Foam::bitSet::operator=(const bool val)
{
PackedList<1>::operator=(val);
return *this;
}
inline Foam::bitSet& Foam::bitSet::operator=(const bitSet& bitset)
{
PackedList<1>::operator=(bitset);
return *this;
}
inline Foam::bitSet& Foam::bitSet::operator=(bitSet&& bitset)
{
transfer(bitset);
return *this;
}
inline Foam::bitSet Foam::bitSet::operator~() const
{
bitSet result(*this);
result.flip();
return result;
}
inline Foam::bitSet& Foam::bitSet::operator&=(const bitSet& other)
{
return andEq(other);
}
inline Foam::bitSet& Foam::bitSet::operator|=(const bitSet& other)
{
return orEq(other);
}
inline Foam::bitSet& Foam::bitSet::operator^=(const bitSet& other)
{
return xorEq(other);
}
inline Foam::bitSet& Foam::bitSet::operator-=(const bitSet& other)
{
return minusEq(other);
}
// * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
inline Foam::bitSet Foam::operator&(const bitSet& a, const bitSet& b)
{
bitSet result(a);
return (result &= b);
}
inline Foam::bitSet Foam::operator|(const bitSet& a, const bitSet& b)
{
bitSet result(a);
return (result |= b);
}
inline Foam::bitSet Foam::operator^(const bitSet& a, const bitSet& b)
{
bitSet result(a);
return (result ^= b);
}
inline Foam::bitSet Foam::operator-(const bitSet& a, const bitSet& b)
{
bitSet result(a);
return (result -= b);
}
// ************************************************************************* //

View File

@ -0,0 +1,135 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 "bitSet.H"
#include "IOstreams.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::bitSet::writeEntry(Ostream& os) const
{
os << *this;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::Ostream& Foam::bitSet::writeList
(
Ostream& os,
const label shortListLen
) const
{
const bitSet& list = *this;
const label len = list.size();
// Write list contents depending on data format
if (os.format() == IOstream::ASCII)
{
if (list.uniform())
{
// Two or more entries, and all entries have identical values.
os << len << token::BEGIN_BLOCK << list[0] << token::END_BLOCK;
}
else if (!shortListLen || len <= shortListLen)
{
// Shorter list, or line-breaks suppressed
os << len << token::BEGIN_LIST;
for (label i=0; i < len; ++i)
{
if (i) os << token::SPACE;
os << list[i];
}
os << token::END_LIST;
}
else
{
// Longer list
os << nl << len << nl << token::BEGIN_LIST << nl;
for (label i=0; i < len; ++i)
{
os << list[i] << nl;
}
os << token::END_LIST << nl;
}
}
else
{
// Contents are binary and contiguous
os << nl << len << nl;
if (len)
{
// write(...) includes surrounding start/end delimiters
os.write
(
reinterpret_cast<const char*>(list.storage().cdata()),
list.byteSize()
);
}
}
return os;
}
void Foam::bitSet::writeEntry
(
const word& keyword,
Ostream& os
) const
{
os.writeKeyword(keyword);
writeEntry(os);
os << token::END_STATEMENT << endl;
}
// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const bitSet& bitset)
{
return bitset.writeList(os, 10);
}
Foam::Ostream& Foam::operator<<
(
Ostream& os,
const InfoProxy<bitSet>& iproxy
)
{
const bitSet& bitset = iproxy.t_;
os << "bitSet<" << bitSet::elem_per_block
<< "> size=" << bitset.size() << "/" << bitset.capacity()
<< " count=" << bitset.count()
<< nl;
return os;
}
// ************************************************************************* //

View File

@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 <algorithm>
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class InputIter>
void Foam::bitSet::setMany(InputIter first, InputIter last)
{
// Check the max expected value first
const auto max = std::max_element(first, last);
const label len = (max != last ? (1 + *max) : 0);
if (len > 0)
{
reserve(len);
for (; first != last; ++first)
{
set(*first);
}
}
}
template<class InputIter>
void Foam::bitSet::unsetMany(InputIter first, InputIter last)
{
for (; first != last; ++first)
{
unset(*first);
}
}
// ************************************************************************* //

View File

@ -24,26 +24,23 @@ License
\*---------------------------------------------------------------------------*/
#include "HashOps.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include <algorithm>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::labelHashSet Foam::HashSetOps::used(const PackedBoolList& select)
Foam::labelHashSet Foam::HashSetOps::used(const bitSet& select)
{
const label count = select.count();
const label len = select.size();
labelHashSet output(0);
labelHashSet output(2*count);
label used = 0;
for (label i = 0; i < len && used < count; ++i)
if (select.any())
{
if (select[i])
output.resize(2*select.count());
for (label i = select.find_first(); i >= 0; i = select.find_next(i))
{
output.insert(i);
++used;
}
}
@ -53,11 +50,10 @@ Foam::labelHashSet Foam::HashSetOps::used(const PackedBoolList& select)
Foam::labelHashSet Foam::HashSetOps::used(const UList<bool>& select)
{
// We have no estimate of the size/sparsity, just assume 1/10
const label len = select.size();
labelHashSet output(len/10);
// No idea of the sparseness, just assume 1/8
labelHashSet output(len/4);
for (label i = 0; i < len; ++i)
{
@ -71,34 +67,19 @@ Foam::labelHashSet Foam::HashSetOps::used(const UList<bool>& select)
}
Foam::PackedBoolList Foam::HashSetOps::bitset(const labelHashSet& labels)
Foam::bitSet Foam::HashSetOps::bitset(const labelHashSet& locations)
{
auto const max = std::max_element(labels.cbegin(), labels.cend());
const label len = (max.found() ? (1 + *max) : 0);
if (len <= 0)
{
return PackedBoolList();
}
PackedBoolList output(len);
for (const label i : labels)
{
if (i >= 0)
{
output.set(i);
}
}
bitSet output;
output.setMany(locations.begin(), locations.end());
return output;
}
Foam::List<bool> Foam::HashSetOps::bools(const labelHashSet& labels)
Foam::List<bool> Foam::HashSetOps::bools(const labelHashSet& locations)
{
auto const max = std::max_element(labels.cbegin(), labels.cend());
const label len = (max.found() ? (1 + *max) : 0);
auto const max = std::max_element(locations.begin(), locations.end());
const label len = (max != locations.end() ? (1 + *max) : 0);
if (len <= 0)
{
@ -107,7 +88,7 @@ Foam::List<bool> Foam::HashSetOps::bools(const labelHashSet& labels)
List<bool> output(len, false);
for (const label i : labels)
for (const label i : locations)
{
if (i >= 0)
{

View File

@ -49,7 +49,7 @@ namespace Foam
// Forward declarations
class PackedBoolList;
class bitSet;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -60,7 +60,7 @@ class PackedBoolList;
namespace HashSetOps
{
//- Combine HashSet operation. Equivalent to 'a += b'
//- Combine HashSet operation. Equivalent to 'a |= b'
template<class Key=word, class Hash=string::hash>
struct plusEqOp
{
@ -68,52 +68,56 @@ struct plusEqOp
void operator()(value_type& a, const value_type& b) const
{
a += b;
a |= b;
}
};
//- Convert a packed list of bits to a labelHashSet of the indices used.
//- Convert a bitset to a labelHashSet of the indices used.
//
// \param selection the list for which a 'true' entry corresponds
// to an index for be added to the labelHashSet
// \param select the bitset for which an \a on entry corresponds
// to an index in the output labelHashSet
//
// \return a labelHashSet of the selected indices
labelHashSet used(const PackedBoolList& select);
//
// This is equivalent of the following code, but more efficiently implemented.
// \code
// bitSet select = ...;
// return labelHashSet(select.toc());
// \endcode
labelHashSet used(const bitSet& select);
//- Convert a list of bools to a labelHashSet of the indices used.
//
// \param selection the list for which a 'true' entry corresponds
// to an index for be added to the labelHashSet
// \param select the boolList for which a \a true entry corresponds
// to an index in the output labelHashSet
//
// \return a labelHashSet of the selected indices
labelHashSet used(const UList<bool>& select);
//- Convert labels to a packed list of bits, with '1' for each
//- non-negative value and '0' for all others.
//- Transform the \a on locations to a bitSet.
//
// \param labels the list of indices.
// \param locations the list of positions corresponding to an \a on bit.
//
// \return a packed bit list of the selected indices
// \return a bitset
//
// \note The operation discards any negative values since these are
// invalid positions in the output list.
PackedBoolList bitset(const labelHashSet& labels);
// \note The operation necessarily discards any negative values since these
// are invalid positions in a bitset.
bitSet bitset(const labelHashSet& locations);
//- Convert labels to a list of bools, with 'true' for each
//- non-negative value and 'false' for all others.
//- Transform the \a on locations to a boolList, with \a true for each
//- non-negative location and \a false for all others.
//
// \param labels the list of indices.
// \param locations the list of positions corresponding to an \a on bit.
//
// \return a bool List of the selected indices
// \return a boolList
//
// \note The operation discards any negative values since these are
// invalid positions in the output list.
List<bool> bools(const labelHashSet& labels);
// \note The operation necessarily discards any negative values since these
// are invalid positions in a boolList.
List<bool> bools(const labelHashSet& locations);
} // End namespace HashSetOps

View File

@ -115,16 +115,16 @@ Foam::labelList Foam::identity(const label len, const label start)
}
Foam::PackedBoolList Foam::reorder
Foam::bitSet Foam::reorder
(
const labelUList& oldToNew,
const PackedBoolList& input,
const bitSet& input,
const bool prune
)
{
const label len = input.size();
PackedBoolList output(len);
bitSet output;
output.reserve(len);
for (label i=0; i < len; ++i)
@ -149,10 +149,6 @@ Foam::PackedBoolList Foam::reorder
output.trim();
}
// Verify addresses (for movable refs)
// Info<< "reordered in " << long(input.storage().cdata()) << nl
// << "reordered out " << long(output.storage().cdata()) << nl;
return output;
}
@ -160,14 +156,11 @@ Foam::PackedBoolList Foam::reorder
void Foam::inplaceReorder
(
const labelUList& oldToNew,
PackedBoolList& input,
bitSet& input,
const bool prune
)
{
input = reorder(oldToNew, input, prune);
// Verify address (for movable refs)
// Info<< "now have " << long(input.storage().cdata()) << nl;
}

View File

@ -45,7 +45,7 @@ SourceFiles
#include "FlatOutput.H"
#include "labelList.H"
#include "HashSet.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "ops.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -126,22 +126,20 @@ void inplaceReorder
//- Reorder the elements of a list.
// Similar to the general templated form, but with auto-vivify
// for PackedBoolList.
PackedBoolList reorder
// Similar to the general templated form, but with auto-vivify for Bitset.
bitSet reorder
(
const labelUList& oldToNew,
const PackedBoolList& input,
const bitSet& input,
const bool prune = false
);
//- Inplace reorder the elements of a list.
// Similar to the general templated form, but with auto-vivify
// for PackedBoolList.
// Similar to the general templated form, but with auto-vivify for bitSet.
void inplaceReorder
(
const labelUList& oldToNew,
PackedBoolList& input,
bitSet& input,
const bool prune = false
);
@ -456,7 +454,7 @@ template<class T>
void setValue
(
UList<T>& list,
const PackedBoolList& locations,
const bitSet& locations,
const T& val
);
@ -578,7 +576,7 @@ template<class T>
List<T> createWithValue
(
const label len,
const PackedBoolList& locations,
const bitSet& locations,
const T& val,
const T& deflt = T()
);

View File

@ -128,7 +128,7 @@ void Foam::inplaceReorder
// the oldToNew map is unique (ie, shuffle)
// Use const reference to ensure we obtain the proper operator[]
// on lazy lists (eg, List<bool>, PackedBoolList)
// on lazy lists (eg, List<bool>, PackedList)
const ListType& input = inputOutput;
const label len = input.size();
@ -439,7 +439,7 @@ ListType Foam::subset
{
const label len = input.size();
// select can have a different size (eg, PackedBoolList, labelHashSet)
// select can have a different size (eg, bitSet, labelHashSet)
ListType output(len);
output.resize(len); // Consistent sizing (eg, DynamicList)
@ -468,7 +468,7 @@ void Foam::inplaceSubset
{
const label len = input.size();
// select can have a different size (eg, PackedBoolList, labelHashSet)
// select can have a different size (eg, bitSet, labelHashSet)
label count = 0;
for (label i=0; i < len; ++i)
@ -979,22 +979,20 @@ template<class T>
void Foam::ListOps::setValue
(
UList<T>& list,
const PackedBoolList& locations,
const bitSet& locations,
const T& val
)
{
// Need improvements in PackedBoolList for more efficiency
const label len = list.size();
const label count = locations.count();
for (label index = 0, used = 0; index < len && used < count; ++index)
for
(
label pos = locations.find_first();
pos >= 0 && pos < len;
pos = locations.find_next(pos)
)
{
if (locations.test(index))
{
list[index] = val;
++used;
}
list[pos] = val;
}
}
@ -1106,7 +1104,7 @@ template<class T>
Foam::List<T> Foam::ListOps::createWithValue
(
const label len,
const PackedBoolList& locations,
const bitSet& locations,
const T& val,
const T& deflt
)

View File

@ -1,217 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ 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"
#include "IOstreams.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::PackedBoolList::bitorPrepare
(
const PackedBoolList& lst,
label& maxPackLen
)
{
const StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage();
const label packLen1 = this->packedLength();
const label packLen2 = lst.packedLength();
// check how the lists interact and if bit trimming is needed
bool needTrim = false;
maxPackLen = packLen1;
if (packLen1 == packLen2)
{
// identical packed lengths - only resize if absolutely necessary
if
(
this->size() != lst.size()
&& maxPackLen
&& rhs[maxPackLen-1] > lhs[maxPackLen-1]
)
{
// second list has a higher bit set
// extend addressable area and use trim
resize(lst.size());
needTrim = true;
}
}
else if (packLen2 < packLen1)
{
// second list is shorter, this limits the or
maxPackLen = packLen2;
}
else
{
// second list is longer, find the highest bit set
for (label storeI = packLen1; storeI < packLen2; ++storeI)
{
if (rhs[storeI])
{
maxPackLen = storeI+1;
}
}
// the upper limit moved - resize for full coverage and trim later
if (maxPackLen > packLen1)
{
resize(maxPackLen * packing());
needTrim = true;
}
}
return needTrim;
}
template<class LabelListType>
void Foam::PackedBoolList::setIndices(const LabelListType& indices)
{
const label len = indices.size();
// No better information, just guess something from the size
reserve(len);
for (label i = 0; i < len; ++i)
{
set(indices[i]);
}
}
template<class LabelListType>
void Foam::PackedBoolList::unsetIndices(const LabelListType& indices)
{
const label len = indices.size();
for (label i = 0; i < len; ++i)
{
unset(indices[i]);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::PackedBoolList::PackedBoolList(Istream& is)
:
PackedList<1>()
{
is >> *this;
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::PackedBoolList::set(const PackedBoolList& lst)
{
// extend addressable area if needed, return maximum size possible
label len = 0;
const bool needTrim = bitorPrepare(lst, len);
// operate directly with the underlying storage
StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage();
for (label i = 0; i < len; ++i)
{
lhs[i] |= rhs[i];
}
if (needTrim)
{
trim();
}
}
void Foam::PackedBoolList::unset(const PackedBoolList& lst)
{
// operate directly with the underlying storage
StorageList& lhs = this->storage();
const StorageList& rhs = lst.storage();
// overlapping storage size
const label len = min(this->packedLength(), lst.packedLength());
for (label i = 0; i < len; ++i)
{
lhs[i] &= ~rhs[i];
}
}
void Foam::PackedBoolList::setMany(const labelUList& indices)
{
setIndices(indices);
}
void Foam::PackedBoolList::setMany(const labelUIndList& indices)
{
setIndices(indices);
}
void Foam::PackedBoolList::unsetMany(const labelUList& indices)
{
unsetIndices(indices);
}
void Foam::PackedBoolList::unsetMany(const labelUIndList& indices)
{
unsetIndices(indices);
}
Foam::labelList Foam::PackedBoolList::used() const
{
// Number of used (set) entries
const label cnt = this->count();
labelList lst(cnt);
if (cnt)
{
// The length of the input list
const label len = this->size();
for (label i=0, usedi=0; (i < len && usedi < cnt); ++i)
{
if (test(i))
{
lst[usedi++] = i;
}
}
}
return lst;
}
// ************************************************************************* //

View File

@ -1,216 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
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.
In addition to the obvious memory advantage over using a
List\<bool\>, this class also provides a number of bit-like
operations.
SourceFiles
PackedBoolListI.H
PackedBoolList.C
See also
Foam::PackedList
\*---------------------------------------------------------------------------*/
#ifndef PackedBoolList_H
#define PackedBoolList_H
#include "PackedList.H"
#include "UIndirectList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration
class PackedBoolList;
//- \typedef A List of PackedBoolList
typedef List<PackedBoolList> PackedBoolListList;
/*---------------------------------------------------------------------------*\
Class PackedBoolList Declaration
\*---------------------------------------------------------------------------*/
class PackedBoolList
:
public PackedList<1>
{
// Private Member Functions
//- Preparation, resizing before a bitor operation
// returns true if the later result needs trimming
bool bitorPrepare(const PackedBoolList& lst, label& maxPackLen);
//- Set the listed indices. Return number of elements changed.
// Does auto-vivify for non-existent entries.
template<class LabelListType>
void setIndices(const LabelListType& indices);
//- Unset the listed indices. Return number of elements changed.
// Never auto-vivify entries.
template<class LabelListType>
void unsetIndices(const LabelListType& indices);
public:
// Constructors
//- Construct null
PackedBoolList() = default;
//- Construct from Istream
PackedBoolList(Istream& is);
//- Construct with given size, initializes list to 0 (false)
explicit inline PackedBoolList(const label size);
//- Construct with given size and value for all elements
inline PackedBoolList(const label size, const bool val);
//- Copy construct
inline PackedBoolList(const PackedBoolList& lst);
//- Move construct
inline PackedBoolList(PackedBoolList&& lst);
//- Construct with given size and list of labels to set as true.
inline PackedBoolList(const label size, const labelUList& indices);
//- Construct with given size and list of labels to set as true.
inline PackedBoolList(const label size, const labelUIndList& indices);
//- Construct from a list of bools
explicit inline PackedBoolList(const UList<bool>& lst);
//- Construct from a list of labels
//- using the labels as indices to indicate which bits are set
explicit inline PackedBoolList(const labelUList& indices);
//- Construct from a list of labels
//- using the labels as indices to indicate which bits are set
explicit inline PackedBoolList(const labelUIndList& indices);
//- Clone
inline autoPtr<PackedBoolList> clone() const;
// Member Functions
// Query
//- Test value at specified position.
// \note Method name compatibility with std::bitset
inline bool test(const label pos) const;
// Access
//- Single index/value assign
using PackedList<1>::set;
//- Single index unassign
using PackedList<1>::unset;
//- Set specified bits.
void set(const PackedBoolList& lst);
//- Unset specified bits.
void unset(const PackedBoolList& lst);
//- Return indices of the used (true) elements as a list of labels
labelList used() const;
// Edit
//- Transfer the contents of the argument list into this list
//- and annul the argument list.
inline void transfer(PackedBoolList& lst);
// Convenience Methods
//- Set the listed indices. Return number of elements changed.
// Does auto-vivify for non-existent entries.
void setMany(const labelUList& indices);
//- Set the listed indices. Return number of elements changed.
// Does auto-vivify for non-existent entries.
void setMany(const labelUIndList& indices);
//- Unset the listed indices. Return number of elements changed.
// Never auto-vivify entries.
void unsetMany(const labelUList& indices);
//- Unset the listed indices. Return number of elements changed.
// Never auto-vivify entries.
void unsetMany(const labelUIndList& indices);
// Member Operators
//- Assign all entries to the given value.
inline void operator=(const bool val);
//- Copy assignment
inline void operator=(const PackedBoolList& lst);
//- Move assignment
inline void operator=(PackedBoolList&& lst);
// Housekeeping
//- No assignment from list. Use setMany for that.
void operator=(const labelUList&) = delete;
//- No assignment from list. Use setMany for that.
void operator=(const labelUIndList&) = delete;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "PackedBoolListI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,152 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
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(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(PackedBoolList&& lst)
:
PackedList<1>()
{
transfer(lst);
}
inline Foam::PackedBoolList::PackedBoolList(const UList<bool>& lst)
:
PackedList<1>(lst.size())
{
// Set according to indices that are true
const label len = lst.size();
for (label i = 0; i < len; ++i)
{
if (lst[i])
{
this->set(i, 1u);
}
}
}
inline Foam::PackedBoolList::PackedBoolList(const labelUList& indices)
:
PackedBoolList((indices.size() ? indices.last() : 0), indices)
{}
inline Foam::PackedBoolList::PackedBoolList(const labelUIndList& indices)
:
PackedBoolList((indices.size() ? indices.last() : 0), indices)
{}
inline Foam::PackedBoolList::PackedBoolList
(
const label size,
const labelUList& indices
)
:
PackedList<1>(size)
{
setMany(indices);
}
inline Foam::PackedBoolList::PackedBoolList
(
const label size,
const labelUIndList& indices
)
:
PackedList<1>(size)
{
setMany(indices);
}
inline Foam::autoPtr<Foam::PackedBoolList>
Foam::PackedBoolList::clone() const
{
return autoPtr<PackedBoolList>::New(*this);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::PackedBoolList::test(const label pos) const
{
return get(pos);
}
inline void Foam::PackedBoolList::transfer(PackedBoolList& lst)
{
PackedList<1>::transfer(static_cast<PackedList<1>&>(lst));
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline void Foam::PackedBoolList::operator=(const bool val)
{
PackedList<1>::operator=(val);
}
inline void Foam::PackedBoolList::operator=(const PackedBoolList& lst)
{
PackedList<1>::operator=(lst);
}
inline void Foam::PackedBoolList::operator=(PackedBoolList&& lst)
{
transfer(lst);
}
// ************************************************************************* //

View File

@ -1,536 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "PackedList.H"
#include "IOstreams.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<unsigned nBits>
void Foam::PackedList<nBits>::writeEntry(Ostream& os) const
{
os << *this;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
#if (UINT_MAX == 0xFFFFFFFF)
// 32-bit counting, Hamming weight method
#define COUNT_PACKEDBITS(sum, x) \
{ \
x -= (x >> 1) & 0x55555555; \
x = (x & 0x33333333) + ((x >> 2) & 0x33333333); \
sum += (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; \
}
#elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
// 64-bit counting, Hamming weight method
#define COUNT_PACKEDBITS(sum, x) \
{ \
x -= (x >> 1) & 0x5555555555555555; \
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); \
sum += (((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101) >> 56; \
}
#else
// Arbitrary number of bits, Brian Kernighan's method
#define COUNT_PACKEDBITS(sum, x) for (; x; ++sum) { x &= x - 1; }
#endif
template<unsigned nBits>
unsigned int Foam::PackedList<nBits>::count() const
{
unsigned int c = 0;
if (size_)
{
const label packLen = packedLength();
for (label i = 0; i < packLen; ++i)
{
unsigned int bits = StorageList::operator[](i);
COUNT_PACKEDBITS(c, bits);
}
}
return c;
}
#undef COUNT_PACKEDBITS
template<unsigned nBits>
bool Foam::PackedList<nBits>::trim()
{
if (!size_)
{
return false;
}
const label oldSize = size_;
for (label storeI = packedLength()-1; storeI >= 0; --storeI)
{
size_ = storeI * packing();
unsigned int bits = StorageList::operator[](storeI);
// found some bits
if (bits)
{
while (bits)
{
bits >>= nBits;
++size_;
}
break;
}
}
return (size_ != oldSize);
}
template<unsigned nBits>
void Foam::PackedList<nBits>::flip()
{
if (!size_)
{
return;
}
// mask value for complete segments
const unsigned int mask = maskLower(packing());
const label packLen = packedLength();
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
{
labelList elems(size_);
for (label i=0; i < size_; ++i)
{
elems[i] = get(i);
}
return elems;
}
template<unsigned nBits>
Foam::Ostream& Foam::PackedList<nBits>::printBits
(
Ostream& os,
const bool fullOutput
) const
{
const label packLen = packedLength();
// mask value for complete segments
unsigned int mask = maskLower(packing());
const label outputLen = fullOutput ? StorageList::size() : packLen;
os << "(\n";
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 == packLen-1)
{
const unsigned int off = size_ % packing();
if (off)
{
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';
}
else
{
os << '-';
}
}
else
{
if (rawBits & testBit)
{
os << '!';
}
else
{
os << '.';
}
}
}
os << '\n';
}
os << ")\n";
return os;
}
template<unsigned nBits>
Foam::Ostream& Foam::PackedList<nBits>::printInfo
(
Ostream& os,
const bool fullOutput
) const
{
os << "PackedList<" << nBits << ">"
<< " max_value:" << max_value()
<< " packing:" << packing() << nl
<< " count: " << count() << nl
<< " size/capacity: " << size_ << "/" << capacity() << nl
<< " storage/capacity: "
<< packedLength() << "/" << StorageList::size()
<< "\n";
return printBits(os, fullOutput);
}
template<unsigned nBits>
Foam::Istream& Foam::PackedList<nBits>::read(Istream& is)
{
PackedList<nBits>& lst = *this;
lst.clear();
is.fatalCheck(FUNCTION_NAME);
token firstTok(is);
is.fatalCheck
(
"PackedList::read(Istream&) : "
"reading first token"
);
if (firstTok.isLabel())
{
const label len = firstTok.labelToken();
// Set list length to that read
lst.resize(len);
// Read list contents depending on data format
if (is.format() == IOstream::ASCII)
{
// Read beginning of contents
const char delimiter = is.readBeginList("PackedList");
if (len)
{
if (delimiter == token::BEGIN_LIST)
{
for (label i=0; i<len; ++i)
{
lst.set(i, lst.readValue(is));
is.fatalCheck
(
"PackedList::read(Istream&) : "
"reading entry"
);
}
}
else if (delimiter == token::BEGIN_BLOCK)
{
// assign for all entries
lst = lst.readValue(is);
is.fatalCheck
(
"PackedList::read(Istream&) : "
"reading the single entry"
);
}
else
{
FatalIOErrorInFunction(is)
<< "incorrect list token, expected '(' or '{', found "
<< firstTok.info()
<< exit(FatalIOError);
}
}
// Read end of contents
is.readEndList("PackedList");
}
else
{
if (len)
{
is.read
(
reinterpret_cast<char*>(lst.storage().data()),
lst.byteSize()
);
is.fatalCheck
(
"PackedList::read(Istream&) : "
"reading the binary block"
);
}
}
}
else if (firstTok.isPunctuation())
{
if (firstTok.pToken() == token::BEGIN_LIST)
{
token nextTok(is);
is.fatalCheck(FUNCTION_NAME);
while
(
!( nextTok.isPunctuation()
&& nextTok.pToken() == token::END_LIST
)
)
{
is.putBack(nextTok);
lst.append(lst.readValue(is));
is >> nextTok;
is.fatalCheck(FUNCTION_NAME);
}
}
else if (firstTok.pToken() == token::BEGIN_BLOCK)
{
token nextTok(is);
is.fatalCheck(FUNCTION_NAME);
while
(
!( nextTok.isPunctuation()
&& nextTok.pToken() == token::END_BLOCK
)
)
{
is.putBack(nextTok);
lst.setPair(is);
is >> nextTok;
is.fatalCheck(FUNCTION_NAME);
}
}
else
{
FatalIOErrorInFunction(is)
<< "incorrect first token, expected '(', found "
<< firstTok.info()
<< exit(FatalIOError);
}
}
else
{
FatalIOErrorInFunction(is)
<< "incorrect first token, expected <int>, '(' or '{', found "
<< firstTok.info()
<< exit(FatalIOError);
}
return is;
}
template<unsigned nBits>
Foam::Ostream& Foam::PackedList<nBits>::writeList
(
Ostream& os,
const label shortListLen
) const
{
const PackedList<nBits>& lst = *this;
const label len = lst.size();
// Write list contents depending on data format
if (os.format() == IOstream::ASCII)
{
// Can the contents be considered 'uniform' (ie, identical)?
bool uniform = (len > 1);
if (uniform)
{
forAll(lst, i)
{
if (lst[i] != lst[0])
{
uniform = false;
break;
}
}
}
if (uniform)
{
// uniform values:
os << len << token::BEGIN_BLOCK << lst[0] << token::END_BLOCK;
}
else if (!shortListLen || len <= shortListLen)
{
// Shorter list, or line-breaks suppressed
os << len << token::BEGIN_LIST;
forAll(lst, i)
{
if (i) os << token::SPACE;
os << lst[i];
}
os << token::END_LIST;
}
else
{
// Longer list
os << nl << len << nl << token::BEGIN_LIST << nl;
forAll(lst, i)
{
os << lst[i] << nl;
}
os << token::END_LIST << nl;
}
}
else
{
// Contents are binary and contiguous
os << nl << len << nl;
if (len)
{
// write(...) includes surrounding start/end delimiters
os.write
(
reinterpret_cast<const char*>(lst.storage().cdata()),
lst.byteSize()
);
}
}
return os;
}
template<unsigned nBits>
void Foam::PackedList<nBits>::writeEntry
(
const word& keyword,
Ostream& os
) const
{
os.writeKeyword(keyword);
writeEntry(os);
os << token::END_STATEMENT << endl;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<unsigned nBits>
void Foam::PackedList<nBits>::operator=(const PackedList<nBits>& lst)
{
StorageList::operator=(lst);
size_ = lst.size();
}
template<unsigned nBits>
void Foam::PackedList<nBits>::operator=(PackedList<nBits>&& lst)
{
transfer(lst);
}
template<unsigned nBits>
void Foam::PackedList<nBits>::operator=(const labelUList& lst)
{
setCapacity(lst.size());
size_ = lst.size();
forAll(lst, i)
{
set(i, lst[i]);
}
}
template<unsigned nBits>
void Foam::PackedList<nBits>::operator=(const labelUIndList& lst)
{
setCapacity(lst.size());
size_ = lst.size();
forAll(lst, i)
{
set(i, lst[i]);
}
}
// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
template<unsigned nBits>
Foam::Istream& Foam::operator>>(Istream& is, PackedList<nBits>& lst)
{
return lst.read(is);
}
template<unsigned nBits>
Foam::Ostream& Foam::operator<<(Ostream& os, const PackedList<nBits>& lst)
{
return lst.writeList(os, 10);
}
// ************************************************************************* //

View File

@ -1,730 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 <climits>
#include "error.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<unsigned nBits>
inline constexpr unsigned int Foam::PackedList<nBits>::max_bits()
{
return sizeof(StorageType)*CHAR_BIT - 1;
}
template<unsigned nBits>
inline constexpr unsigned int Foam::PackedList<nBits>::max_value()
{
return (1u << nBits) - 1;
}
template<unsigned nBits>
inline constexpr unsigned int Foam::PackedList<nBits>::packing()
{
return sizeof(StorageType)*CHAR_BIT / nBits;
}
template<unsigned nBits>
inline constexpr unsigned int Foam::PackedList<nBits>::maskLower
(
unsigned offset
)
{
// Return (1u << (nBits * offset)) - 1;
// The next one works more reliably with overflows
// eg, when compiled without optimization
return (~0u >> (sizeof(StorageType)*CHAR_BIT - nBits * offset));
}
template<unsigned nBits>
inline constexpr Foam::label Foam::PackedList<nBits>::packedLength
(
const label nElem
)
{
return (nElem + packing() - 1) / packing();
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
namespace Foam
{
// Template specialization for bool entries
template<> inline unsigned int PackedList<1>::readValue(Istream& is)
{
return readBool(is);
}
// Template specialization for bool entries
template<> inline void PackedList<1>::setPair(Istream& is)
{
set(readLabel(is), true);
}
}
template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::readValue(Istream& is)
{
const unsigned int val = readLabel(is);
if (val > max_value())
{
FatalIOErrorInFunction(is)
<< "Out-of-range value " << val << " for PackedList<" << nBits
<< ">. Maximum permitted value is " << max_value() << "."
<< exit(FatalIOError);
}
return val;
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::setPair(Istream& is)
{
is.readBegin("Tuple2<label,unsigned int>");
const label ind = readLabel(is);
const unsigned int val = readLabel(is);
is.readEnd("Tuple2<label,unsigned int>");
if (val > max_value())
{
FatalIOErrorInFunction(is)
<< "Out-of-range value " << val << " for PackedList<" << nBits
<< "> at index " << ind
<< ". Maximum permitted value is " << max_value() << "."
<< exit(FatalIOError);
}
set(ind, val);
is.check(FUNCTION_NAME);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList()
:
PackedListCore(),
StorageList(),
size_(0)
{}
template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList(const label size)
:
PackedListCore(),
StorageList(packedLength(size), 0u),
size_(size)
{}
template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList
(
const label size,
const unsigned int val
)
:
PackedListCore(),
StorageList(packedLength(size), 0u),
size_(size)
{
if (val)
{
operator=(val);
}
}
template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList(Istream& is)
:
PackedListCore(),
StorageList(),
size_(0)
{
read(is);
}
template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList(const PackedList<nBits>& lst)
:
PackedListCore(),
StorageList(lst),
size_(lst.size_)
{}
template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList(PackedList<nBits>&& lst)
:
PackedListCore(),
StorageList(),
size_(0)
{
transfer(lst);
}
template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList(const labelUList& lst)
:
PackedListCore(),
StorageList(packedLength(lst.size()), 0u),
size_(lst.size())
{
const label len = lst.size();
for (label i = 0; i < len; ++i)
{
set(i, lst[i]);
}
}
template<unsigned nBits>
inline Foam::PackedList<nBits>::PackedList(const labelUIndList& lst)
:
PackedListCore(),
StorageList(packedLength(lst.size()), 0u),
size_(lst.size())
{
const label len = lst.size();
for (label i = 0; i < len; ++i)
{
set(i, lst[i]);
}
}
template<unsigned nBits>
inline Foam::autoPtr<Foam::PackedList<nBits>>
Foam::PackedList<nBits>::clone() const
{
return autoPtr<PackedList<nBits>>::New(*this);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<unsigned nBits>
inline void Foam::PackedList<nBits>::checkIndex(const label i) const
{
if (!size_)
{
FatalErrorInFunction
<< "attempt to access element " << i << " from zero sized list"
<< abort(FatalError);
}
else if (i < 0 || i >= size_)
{
FatalErrorInFunction
<< "index " << i << " out of range [0," << size_ << ")"
<< abort(FatalError);
}
}
// * * * * * * * * * * * * * * * * Reference * * * * * * * * * * * * * * * * //
template<unsigned nBits>
inline Foam::PackedList<nBits>::reference::reference
(
PackedList* list,
const label index
)
:
ref_(list->StorageList::operator[](index / packing())),
shift_(nBits * (index % packing()))
{}
template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::reference::get() const
{
return ((ref_ >> shift_) & max_value());
}
template<unsigned nBits>
inline bool Foam::PackedList<nBits>::reference::set(const unsigned int val)
{
const unsigned int prev = ref_;
const unsigned int mask = max_value() << shift_;
if (val >= max_value())
{
// Overflow is max_value, fill everything
ref_ |= mask;
}
else
{
ref_ &= ~mask;
ref_ |= mask & (val << shift_);
}
return (prev != ref_);
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::reference::operator=
(
const reference& other
)
{
this->set(other.get());
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::reference::operator=
(
const unsigned int val
)
{
this->set(val);
}
template<unsigned nBits>
inline Foam::PackedList<nBits>::reference::operator unsigned int () const
{
return this->get();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<unsigned nBits>
inline Foam::label Foam::PackedList<nBits>::size() const
{
return size_;
}
template<unsigned nBits>
inline bool Foam::PackedList<nBits>::empty() const
{
return !size_;
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::resize
(
const label newSize,
const unsigned int val
)
{
reserve(newSize);
const label oldSize = size_;
size_ = newSize;
if (size_ > oldSize)
{
// Fill new elements or newly exposed elements
if (val)
{
// Fill value for complete segments
unsigned int fill = val;
if (val >= max_value())
{
// Fill everything
fill = maskLower(packing());
}
else
{
for (unsigned int i = 1; i < packing(); ++i)
{
fill |= (fill << nBits);
}
}
// Fill in complete segments
const label oldLen = packedLength(oldSize);
const label newLen = packedLength(size_);
for (label i=oldLen; i < newLen; ++i)
{
StorageList::operator[](i) = fill;
}
// Finish previous partial segment, preserve existing value
{
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 if (size_ < oldSize)
{
// Resize shrinking
// - clear newly exposed elements
// 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);
}
}
}
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::setSize
(
const label newSize,
const unsigned int val
)
{
resize(newSize, val);
}
template<unsigned nBits>
inline Foam::label Foam::PackedList<nBits>::capacity() const
{
return packing() * StorageList::size();
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::setCapacity(const label nElem)
{
StorageList::setSize(packedLength(nElem), 0u);
// 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);
}
}
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::reserve(const label nElem)
{
const label len = packedLength(nElem);
// Allocate more capacity if necessary
if (len > StorageList::size())
{
StorageList::setSize
(
max
(
len,
// SizeInc=0, SizeMult=2, SizeDiv=1
2 * StorageList::size()
),
0u
);
}
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::reset()
{
StorageList::operator=(0u);
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::clear()
{
reset();
size_ = 0;
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::clearStorage()
{
StorageList::clear();
size_ = 0;
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::shrink()
{
// Any unneeded space allocated?
const label len = packedLength();
if (len < StorageList::size())
{
StorageList::setSize(len);
}
}
template<unsigned nBits>
inline Foam::List<unsigned int>& Foam::PackedList<nBits>::storage()
{
return static_cast<StorageList&>(*this);
}
template<unsigned nBits>
inline const Foam::List<unsigned int>& Foam::PackedList<nBits>::storage() const
{
return static_cast<const StorageList&>(*this);
}
template<unsigned nBits>
inline Foam::label Foam::PackedList<nBits>::packedLength() const
{
return packedLength(size_);
}
template<unsigned nBits>
inline std::streamsize Foam::PackedList<nBits>::byteSize() const
{
return packedLength() * sizeof(StorageType);
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::transfer(PackedList<nBits>& lst)
{
size_ = lst.size_;
lst.size_ = 0;
StorageList::transfer(lst);
}
template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::get(const label i) const
{
// Lazy evaluation - return 0 for out-of-range
if (i < 0 || i >= size_)
{
return 0u;
}
return reference(const_cast<PackedList<nBits>*>(this), i).get();
}
template<unsigned nBits>
inline bool Foam::PackedList<nBits>::set
(
const label i,
const unsigned int val
)
{
if (i < 0)
{
// Lazy evaluation - ignore out-of-bounds
return false;
}
else if (i >= size_)
{
if (!val)
{
// Same as unset out-of-bounds = noop
return false;
}
// Lazy evaluation - increase size on assignment
resize(i + 1);
}
return reference(this, i).set(val);
}
template<unsigned nBits>
inline bool Foam::PackedList<nBits>::unset(const label i)
{
// Unset out-of-bounds = noop
if (i < 0 || i >= size_)
{
return false;
}
return reference(this, i).set(0u);
}
template<unsigned nBits>
inline Foam::PackedList<nBits>&
Foam::PackedList<nBits>::append(const unsigned int val)
{
const label idx = size_;
reserve(idx + 1);
size_++;
reference(this, idx).set(val);
return *this;
}
template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::remove()
{
// Location of last element and simultaneously the new size
const label idx = size_ - 1;
if (idx < 0)
{
FatalErrorInFunction
<< "List is empty" << abort(FatalError);
}
const unsigned int val = reference(this, idx).get();
resize(idx);
return val;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<unsigned nBits>
inline unsigned int Foam::PackedList<nBits>::operator[](const label i) const
{
return get(i);
}
template<unsigned nBits>
inline typename Foam::PackedList<nBits>::reference
Foam::PackedList<nBits>::operator[](const label i)
{
// Leave enabled during testing period (MAR-2018)
// #ifdef FULLDEBUG
checkIndex(i);
// #endif
return reference(this, i);
}
template<unsigned nBits>
inline void Foam::PackedList<nBits>::operator=(const unsigned int val)
{
const label packLen = packedLength();
if (val && size_)
{
unsigned int fill = val;
if (val >= max_value())
{
// Fill everything
fill = maskLower(packing());
}
else
{
for (unsigned int i = 1; i < packing(); ++i)
{
fill |= (fill << nBits);
}
}
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
{
for (label i=0; i < packLen; ++i)
{
StorageList::operator[](i) = 0u;
}
}
}
// ************************************************************************* //

View File

@ -35,7 +35,7 @@ Description
#include "IOstreams.H"
#include "DynamicList.H"
#include "ListOps.H"
#include "PackedBoolList.H"
#include "bitSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -46,7 +46,7 @@ Foam::labelList Foam::bandCompression(const labelListList& cellCellAddressing)
// the business bit of the renumbering
SLList<label> nextCell;
PackedBoolList visited(cellCellAddressing.size());
bitSet visited(cellCellAddressing.size());
label cellInOrder = 0;
@ -171,7 +171,7 @@ Foam::labelList Foam::bandCompression
// the business bit of the renumbering
SLList<label> nextCell;
PackedBoolList visited(offsets.size()-1);
bitSet visited(offsets.size()-1);
label cellInOrder = 0;

View File

@ -29,7 +29,7 @@ Description
#include "cell.H"
#include "oppositeFace.H"
#include "boolList.H"
#include "bitSet.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -136,7 +136,7 @@ Foam::oppositeFace Foam::cell::opposingFace
// Get cell edges
const edgeList e = edges(meshFaces);
boolList usedEdges(e.size(), false);
bitSet usedEdges(e.size());
oppositeFace oppFace
(
@ -151,7 +151,7 @@ Foam::oppositeFace Foam::cell::opposingFace
// to the slave face
forAll(e, edgeI)
{
if (!usedEdges[edgeI])
if (!usedEdges.test(edgeI))
{
// Get the other vertex
label otherVertex = e[edgeI].otherVertex(masterFace[pointi]);
@ -165,7 +165,7 @@ Foam::oppositeFace Foam::cell::opposingFace
{
if (slaveFace[slavePointi] == otherVertex)
{
usedEdges[edgeI] = true;
usedEdges.set(edgeI);
oppFace[pointi] = otherVertex;
break;

View File

@ -27,7 +27,6 @@ License
#include "pointBoundaryMesh.H"
#include "pointMesh.H"
#include "demandDrivenData.H"
#include "boolList.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -1187,9 +1187,9 @@ void Foam::globalMeshData::calcGlobalEdgeOrientation() const
// Now check my edges on how they relate to the master's edgeVerts
globalEdgeOrientationPtr_.reset
(
new PackedBoolList(coupledPatch().nEdges())
new bitSet(coupledPatch().nEdges())
);
PackedBoolList& globalEdgeOrientation = globalEdgeOrientationPtr_();
bitSet& globalEdgeOrientation = globalEdgeOrientationPtr_();
forAll(coupledPatch().edges(), edgeI)
{
@ -2260,7 +2260,7 @@ const
}
const Foam::PackedBoolList& Foam::globalMeshData::globalEdgeOrientation() const
const Foam::bitSet& Foam::globalMeshData::globalEdgeOrientation() const
{
if (!globalEdgeOrientationPtr_.valid())
{
@ -2439,7 +2439,7 @@ Foam::autoPtr<Foam::globalIndex> Foam::globalMeshData::mergePoints
// 1. Count number of masters on my processor.
label nMaster = 0;
PackedBoolList isMaster(mesh_.nPoints(), true);
bitSet isMaster(mesh_.nPoints(), true);
forAll(pointSlaves, pointi)
{
if (masterGlobalPoint[pointi] == -1)

View File

@ -90,14 +90,13 @@ SourceFiles
namespace Foam
{
// Forward declaration of friend functions and operators
// Forward declarations
class polyMesh;
class mapDistribute;
template<class T> class EdgeMap;
class globalIndex;
class globalIndexAndTransform;
class PackedBoolList;
class bitSet;
/*---------------------------------------------------------------------------*\
Class globalMeshData Declaration
@ -171,7 +170,7 @@ class globalMeshData
mutable autoPtr<globalIndex> globalEdgeNumberingPtr_;
mutable autoPtr<labelListList> globalEdgeSlavesPtr_;
mutable autoPtr<labelListList> globalEdgeTransformedSlavesPtr_;
mutable autoPtr<PackedBoolList> globalEdgeOrientationPtr_;
mutable autoPtr<bitSet> globalEdgeOrientationPtr_;
mutable autoPtr<mapDistribute> globalEdgeSlavesMapPtr_;
@ -545,7 +544,7 @@ public:
const labelListList& globalEdgeTransformedSlaves() const;
const mapDistribute& globalEdgeSlavesMap() const;
//- Is my edge same orientation as master edge
const PackedBoolList& globalEdgeOrientation() const;
const bitSet& globalEdgeOrientation() const;
// Collocated point to collocated point

View File

@ -70,7 +70,7 @@ bool Foam::polyMesh::checkFaceOrthogonality
// Statistics only for internal and masters of coupled faces
PackedBoolList isMasterFace(syncTools::getInternalOrMasterFaces(*this));
bitSet isMasterFace(syncTools::getInternalOrMasterFaces(*this));
forAll(ortho, facei)
{
@ -203,7 +203,7 @@ bool Foam::polyMesh::checkFaceSkewness
label nWarnSkew = 0;
// Statistics only for all faces except slave coupled faces
PackedBoolList isMasterFace(syncTools::getMasterFaces(*this));
bitSet isMasterFace(syncTools::getMasterFaces(*this));
forAll(skew, facei)
{
@ -518,7 +518,7 @@ bool Foam::polyMesh::checkFaceWeight
label nSummed = 0;
// Statistics only for internal and masters of coupled faces
PackedBoolList isMasterFace(syncTools::getInternalOrMasterFaces(*this));
bitSet isMasterFace(syncTools::getInternalOrMasterFaces(*this));
forAll(faceWght, facei)
{
@ -605,7 +605,7 @@ bool Foam::polyMesh::checkVolRatio
label nSummed = 0;
// Statistics only for internal and masters of coupled faces
PackedBoolList isMasterFace(syncTools::getInternalOrMasterFaces(*this));
bitSet isMasterFace(syncTools::getInternalOrMasterFaces(*this));
forAll(volRatio, facei)
{

View File

@ -62,10 +62,10 @@ void Foam::syncTools::swapBoundaryCellPositions
}
Foam::PackedBoolList Foam::syncTools::getMasterPoints(const polyMesh& mesh)
Foam::bitSet Foam::syncTools::getMasterPoints(const polyMesh& mesh)
{
PackedBoolList isMasterPoint(mesh.nPoints());
PackedBoolList donePoint(mesh.nPoints());
bitSet isMasterPoint(mesh.nPoints());
bitSet donePoint(mesh.nPoints());
const globalMeshData& globalData = mesh.globalData();
const labelList& meshPoints = globalData.coupledPatch().meshPoints();
@ -96,7 +96,7 @@ Foam::PackedBoolList Foam::syncTools::getMasterPoints(const polyMesh& mesh)
forAll(donePoint, pointi)
{
if (!donePoint[pointi])
if (!donePoint.test(pointi))
{
isMasterPoint.set(pointi);
}
@ -106,10 +106,10 @@ Foam::PackedBoolList Foam::syncTools::getMasterPoints(const polyMesh& mesh)
}
Foam::PackedBoolList Foam::syncTools::getMasterEdges(const polyMesh& mesh)
Foam::bitSet Foam::syncTools::getMasterEdges(const polyMesh& mesh)
{
PackedBoolList isMasterEdge(mesh.nEdges());
PackedBoolList doneEdge(mesh.nEdges());
bitSet isMasterEdge(mesh.nEdges());
bitSet doneEdge(mesh.nEdges());
const globalMeshData& globalData = mesh.globalData();
const labelList& meshEdges = globalData.coupledPatchMeshEdges();
@ -140,7 +140,7 @@ Foam::PackedBoolList Foam::syncTools::getMasterEdges(const polyMesh& mesh)
forAll(doneEdge, edgeI)
{
if (!doneEdge[edgeI])
if (!doneEdge.test(edgeI))
{
isMasterEdge.set(edgeI);
}
@ -150,9 +150,9 @@ Foam::PackedBoolList Foam::syncTools::getMasterEdges(const polyMesh& mesh)
}
Foam::PackedBoolList Foam::syncTools::getMasterFaces(const polyMesh& mesh)
Foam::bitSet Foam::syncTools::getMasterFaces(const polyMesh& mesh)
{
PackedBoolList isMasterFace(mesh.nFaces(), true);
bitSet isMasterFace(mesh.nFaces(), true);
const polyBoundaryMesh& patches = mesh.boundaryMesh();
@ -177,12 +177,12 @@ Foam::PackedBoolList Foam::syncTools::getMasterFaces(const polyMesh& mesh)
}
Foam::PackedBoolList Foam::syncTools::getInternalOrMasterFaces
Foam::bitSet Foam::syncTools::getInternalOrMasterFaces
(
const polyMesh& mesh
)
{
PackedBoolList isMasterFace(mesh.nFaces(), true);
bitSet isMasterFace(mesh.nFaces(), true);
const polyBoundaryMesh& patches = mesh.boundaryMesh();
@ -213,12 +213,12 @@ Foam::PackedBoolList Foam::syncTools::getInternalOrMasterFaces
}
Foam::PackedBoolList Foam::syncTools::getInternalOrCoupledFaces
Foam::bitSet Foam::syncTools::getInternalOrCoupledFaces
(
const polyMesh& mesh
)
{
PackedBoolList isMasterFace(mesh.nFaces(), true);
bitSet isMasterFace(mesh.nFaces(), true);
const polyBoundaryMesh& patches = mesh.boundaryMesh();

View File

@ -44,7 +44,7 @@ SourceFiles
#include "Pstream.H"
#include "EdgeMap.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "polyMesh.H"
#include "coupledPolyPatch.H"
#include "mapDistribute.H"
@ -590,22 +590,22 @@ public:
//- Get per point whether it is uncoupled or a master of a
// coupled set of points
static PackedBoolList getMasterPoints(const polyMesh&);
static bitSet getMasterPoints(const polyMesh&);
//- Get per edge whether it is uncoupled or a master of a
// coupled set of edges
static PackedBoolList getMasterEdges(const polyMesh&);
static bitSet getMasterEdges(const polyMesh&);
//- Get per face whether it is uncoupled or a master of a
// coupled set of faces
static PackedBoolList getMasterFaces(const polyMesh&);
static bitSet getMasterFaces(const polyMesh&);
//- Get per face whether it is internal or a master of a
// coupled set of faces
static PackedBoolList getInternalOrMasterFaces(const polyMesh&);
static bitSet getInternalOrMasterFaces(const polyMesh&);
//- Get per face whether it is internal or coupled
static PackedBoolList getInternalOrCoupledFaces(const polyMesh&);
static bitSet getInternalOrCoupledFaces(const polyMesh&);
};

View File

@ -435,12 +435,12 @@ Foam::label Foam::ZoneMesh<ZoneType, MeshType>::findZoneID
template<class ZoneType, class MeshType>
Foam::PackedBoolList Foam::ZoneMesh<ZoneType, MeshType>::findMatching
Foam::bitSet Foam::ZoneMesh<ZoneType, MeshType>::findMatching
(
const keyType& key
) const
{
PackedBoolList bitset;
bitSet bitset;
const labelList indices = this->findIndices(key);
forAll(indices, i)

View File

@ -39,7 +39,7 @@ SourceFiles
#include "regIOobject.H"
#include "pointField.H"
#include "Map.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "wordRes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -180,7 +180,7 @@ public:
label findZoneID(const word& zoneName) const;
//- Mark items (cells, faces, points) that match the zone specification
PackedBoolList findMatching(const keyType& key) const;
bitSet findMatching(const keyType& key) const;
//- Clear addressing
void clearAddressing();

View File

@ -55,8 +55,9 @@ SourceFiles
namespace Foam
{
// Forward declarations
class polyMesh;
class PackedBoolList;
class bitSet;
class boundBox;
/*---------------------------------------------------------------------------*\
@ -249,7 +250,7 @@ public:
labelList& p1EdgeLabels,
labelList& p2EdgeLabels,
PackedBoolList& sameOrientation
bitSet& sameOrientation
);

View File

@ -91,7 +91,7 @@ void Foam::PatchTools::matchEdges
labelList& p1EdgeLabels,
labelList& p2EdgeLabels,
PackedBoolList& sameOrientation
bitSet& sameOrientation
)
{
p1EdgeLabels.setSize(p1.nEdges());

View File

@ -27,7 +27,7 @@ Description
\*---------------------------------------------------------------------------*/
#include "PatchTools.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "boundBox.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -174,7 +174,7 @@ Foam::PatchTools::subsetMap
faceMap.setSize(localFaces.size());
pointMap.setSize(p.nPoints());
boolList pointHad(pointMap.size(), false);
bitSet pointHad(pointMap.size(), false);
forAll(p, oldFacei)
{
@ -189,9 +189,8 @@ Foam::PatchTools::subsetMap
forAll(f, fp)
{
const label ptLabel = f[fp];
if (!pointHad[ptLabel])
if (pointHad.set(ptLabel))
{
pointHad[ptLabel] = true;
pointMap[pointi++] = ptLabel;
}
}
@ -222,7 +221,7 @@ void Foam::PatchTools::calcBounds
// ourselves
const PointField& points = p.points();
PackedBoolList pointIsUsed(points.size());
bitSet pointIsUsed(points.size());
nPoints = 0;
bb = boundBox::invertedBox;

View File

@ -66,7 +66,8 @@ SourceFiles
namespace Foam
{
class PackedBoolList;
// Forward declarations
class bitSet;
/*---------------------------------------------------------------------------*\
Class primitiveMesh Declaration
@ -296,7 +297,7 @@ protected:
(
const vectorField& areas,
const bool report,
const PackedBoolList& internalOrCoupledFaces
const bitSet& internalOrCoupledFaces
) const;
//- Check cells for closedness

View File

@ -46,7 +46,7 @@ bool Foam::primitiveMesh::checkClosedBoundary
(
const vectorField& areas,
const bool report,
const PackedBoolList& internalOrCoupledFaces
const bitSet& internalOrCoupledFaces
) const
{
if (debug)
@ -1684,7 +1684,7 @@ bool Foam::primitiveMesh::checkFaceFaces
bool Foam::primitiveMesh::checkClosedBoundary(const bool report) const
{
return checkClosedBoundary(faceAreas(), report, PackedBoolList());
return checkClosedBoundary(faceAreas(), report, bitSet());
}

View File

@ -455,7 +455,7 @@ Foam::tmp<Foam::scalarField> Foam::primitiveMeshTools::cellDeterminant
const primitiveMesh& mesh,
const Vector<label>& meshD,
const vectorField& faceAreas,
const PackedBoolList& internalOrCoupledFace
const bitSet& internalOrCoupledFace
)
{
// Determine number of dimensions and (for 2D) missing dimension

View File

@ -35,7 +35,7 @@ SourceFiles
#define primitiveMeshTools_H
#include "primitiveMesh.H"
#include "PackedBoolList.H"
#include "bitSet.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -125,7 +125,7 @@ public:
const primitiveMesh& mesh,
const Vector<label>& directions,
const vectorField& faceAreas,
const PackedBoolList& internalOrCoupledFace
const bitSet& internalOrCoupledFace
);

View File

@ -35,7 +35,7 @@ License
#include "uindirectPrimitivePatch.H"
#include "SortableList.H"
#include "mergePoints.H"
#include "PackedBoolList.H"
#include "bitSet.H"
#include "ListOps.H"
#include "ccmInternal.H" // include last to avoid any strange interactions
@ -1099,7 +1099,7 @@ void Foam::ccm::reader::juggleSolids()
// Identify solid cells
// ~~~~~~~~~~~~~~~~~~~~
label nSolids = 0;
boolList solidCells(cellTableId_.size(), false);
bitSet solidCells(cellTableId_.size(), false);
{
Map<word> solidMap = cellTable_.solids();
@ -1107,7 +1107,7 @@ void Foam::ccm::reader::juggleSolids()
{
if (solidMap.found(cellTableId_[cellI]))
{
solidCells[cellI] = true;
solidCells.set(cellI);
++nSolids;
}
}
@ -1130,7 +1130,7 @@ void Foam::ccm::reader::juggleSolids()
label faceI = patchStarts[patchIndex] + i;
label cellI = faceOwner_[faceI];
if (solidCells[cellI])
if (solidCells.test(cellI))
{
++adjustPatch;
}
@ -1186,7 +1186,7 @@ void Foam::ccm::reader::juggleSolids()
label faceI = patchStarts[patchIndex] + i;
label cellI = faceOwner_[faceI];
if (solidCells[cellI])
if (solidCells.test(cellI))
{
oldToNew[faceI] = solidFace++;
}
@ -1213,7 +1213,7 @@ void Foam::ccm::reader::removeUnwanted()
// Identify fluid/porous/solid cells for removal
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
label nRemove = 0;
boolList removeCells(cellTableId_.size(), false);
bitSet removeCells(cellTableId_.size(), false);
{
Map<word> fluidMap = cellTable_.fluids();
@ -1236,7 +1236,7 @@ void Foam::ccm::reader::removeUnwanted()
: false
)
{
removeCells[cellI] = true;
removeCells.set(cellI);
++nRemove;
removeMap.set(tableId, cellTable_.name(tableId));
}
@ -1291,7 +1291,7 @@ void Foam::ccm::reader::removeUnwanted()
for (label faceI = 0; faceI < nFaces_; ++faceI)
{
label cellI = faceOwner_[faceI];
if (removeCells[cellI])
if (removeCells.test(cellI))
{
if (faceI < nInternalFaces_)
{
@ -1356,7 +1356,7 @@ void Foam::ccm::reader::removeUnwanted()
oldToNew.setSize(nCells_, -1);
for (label cellI = 0; cellI < nCells_; ++cellI)
{
if (!removeCells[cellI])
if (!removeCells.test(cellI))
{
if (nCell != cellI)
{
@ -1886,7 +1886,7 @@ void Foam::ccm::reader::mergeInplaceInterfaces()
label nMergedTotal = 0;
// Markup points to merge
PackedBoolList whichPoints(points_.size());
bitSet whichPoints(points_.size());
Info<< "interface merge points (tol="
<< option().mergeTol() << "):" << endl;
@ -1923,7 +1923,7 @@ void Foam::ccm::reader::mergeInplaceInterfaces()
}
// The global addresses
labelList addr(whichPoints.used());
labelList addr(whichPoints.toc());
const UIndirectList<point> pointsToMerge(points_, addr);

View File

@ -222,7 +222,7 @@ void Foam::ensightMesh::correct()
if (option().useFaceZones())
{
// Mark boundary faces to be excluded from export
PackedBoolList excludeFace(mesh_.nFaces()); // all false
bitSet excludeFace(mesh_.nFaces()); // all false
forAll(mesh_.boundaryMesh(), patchi)
{

View File

@ -32,6 +32,7 @@ InClass
#include "Time.H"
#include "SortableList.H"
#include "pointSet.H"
#include "bitSet.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -594,7 +595,7 @@ void Foam::polyDualMesh::dualPatch
// 3 : done both
labelList doneEdgeSide(meshEdges.size(), 0);
boolList donePoint(patch.nPoints(), false);
bitSet donePoint(patch.nPoints(), false);
// Do points on edge of patch
@ -650,7 +651,7 @@ void Foam::polyDualMesh::dualPatch
dualRegion.append(patch.index());
doneEdgeSide[patchEdgeI] |= bitMask;
donePoint[pointi] = true;
donePoint.set(pointi);
}
}
}
@ -663,7 +664,7 @@ void Foam::polyDualMesh::dualPatch
forAll(donePoint, pointi)
{
if (!donePoint[pointi])
if (!donePoint.test(pointi))
{
labelList dualFace, featEdgeIndices;
@ -1496,7 +1497,7 @@ void Foam::polyDualMesh::calcFeatures
const vectorField& faceNormals = allBoundary.faceNormals();
const labelList& meshPoints = allBoundary.meshPoints();
boolList isFeatureEdge(edgeFaces.size(), false);
bitSet isFeatureEdge(edgeFaces.size(), false);
forAll(edgeFaces, edgeI)
{
@ -1514,11 +1515,11 @@ void Foam::polyDualMesh::calcFeatures
<< " has more than 2 faces connected to it:"
<< eFaces.size() << endl;
isFeatureEdge[edgeI] = true;
isFeatureEdge.set(edgeI);
}
else if (allRegion[eFaces[0]] != allRegion[eFaces[1]])
{
isFeatureEdge[edgeI] = true;
isFeatureEdge.set(edgeI);
}
else if
(
@ -1526,7 +1527,7 @@ void Foam::polyDualMesh::calcFeatures
< featureCos
)
{
isFeatureEdge[edgeI] = true;
isFeatureEdge.set(edgeI);
}
}
@ -1546,9 +1547,9 @@ void Foam::polyDualMesh::calcFeatures
forAll(pEdges, i)
{
if (isFeatureEdge[pEdges[i]])
if (isFeatureEdge.test(pEdges[i]))
{
nFeatEdges++;
++nFeatEdges;
}
}
if (nFeatEdges > 2)
@ -1593,7 +1594,7 @@ void Foam::polyDualMesh::calcFeatures
DynamicList<label> allFeatureEdges(isFeatureEdge.size());
forAll(isFeatureEdge, edgeI)
{
if (isFeatureEdge[edgeI])
if (isFeatureEdge.test(edgeI))
{
// Store in mesh edge label.
allFeatureEdges.append(meshEdges[edgeI]);

View File

@ -46,7 +46,7 @@ namespace Foam
Foam::label Foam::dynamicRefineFvMesh::count
(
const PackedBoolList& l,
const bitSet& l,
const unsigned int val
)
{
@ -72,7 +72,7 @@ Foam::label Foam::dynamicRefineFvMesh::count
void Foam::dynamicRefineFvMesh::calculateProtectedCells
(
PackedBoolList& unrefineableCell
bitSet& unrefineableCell
) const
{
if (protectedCell_.empty())
@ -426,7 +426,7 @@ Foam::dynamicRefineFvMesh::refine
// Update numbering of protectedCell_
if (protectedCell_.size())
{
PackedBoolList newProtectedCell(nCells());
bitSet newProtectedCell(nCells());
forAll(newProtectedCell, celli)
{
@ -589,7 +589,7 @@ Foam::dynamicRefineFvMesh::unrefine
// Update numbering of protectedCell_
if (protectedCell_.size())
{
PackedBoolList newProtectedCell(nCells());
bitSet newProtectedCell(nCells());
forAll(newProtectedCell, celli)
{
@ -692,7 +692,7 @@ void Foam::dynamicRefineFvMesh::selectRefineCandidates
const scalar lowerRefineLevel,
const scalar upperRefineLevel,
const scalarField& vFld,
PackedBoolList& candidateCell
bitSet& candidateCell
) const
{
// Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
@ -725,7 +725,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
(
const label maxCells,
const label maxRefinement,
const PackedBoolList& candidateCell
const bitSet& candidateCell
) const
{
// Every refined cell causes 7 extra cells
@ -735,7 +735,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
// Mark cells that cannot be refined since they would trigger refinement
// of protected cells (since 2:1 cascade)
PackedBoolList unrefineableCell;
bitSet unrefineableCell;
calculateProtectedCells(unrefineableCell);
// Count current selection
@ -806,7 +806,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
(
const scalar unrefineLevel,
const PackedBoolList& markedCell,
const bitSet& markedCell,
const scalarField& pFld
) const
{
@ -819,7 +819,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
// If we have any protected cells make sure they also are not being
// unrefined
PackedBoolList protectedPoint(nPoints());
bitSet protectedPoint(nPoints());
if (protectedCell_.size())
{
@ -911,7 +911,7 @@ Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
void Foam::dynamicRefineFvMesh::extendMarkedCells
(
PackedBoolList& markedCell
bitSet& markedCell
) const
{
// Mark faces using any marked cell
@ -953,7 +953,7 @@ void Foam::dynamicRefineFvMesh::extendMarkedCells
void Foam::dynamicRefineFvMesh::checkEightAnchorPoints
(
PackedBoolList& protectedCell,
bitSet& protectedCell,
label& nProtected
) const
{
@ -1277,7 +1277,7 @@ bool Foam::dynamicRefineFvMesh::update()
readLabel(refineDict.lookup("nBufferLayers"));
// Cells marked for refinement or otherwise protected from unrefinement.
PackedBoolList refineCell(nCells());
bitSet refineCell(nCells());
// Determine candidates for refinement (looking at field only)
selectRefineCandidates
@ -1318,7 +1318,7 @@ bool Foam::dynamicRefineFvMesh::update()
const labelList& cellMap = map().cellMap();
const labelList& reverseCellMap = map().reverseCellMap();
PackedBoolList newRefineCell(cellMap.size());
bitSet newRefineCell(cellMap.size());
forAll(cellMap, celli)
{

Some files were not shown because too many files have changed in this diff Show More