Commit 35facb82 authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: add PackedList::unpack() method

- allows for simpler unpacking of a full list, or list range into any
  sufficiently large integral type.

  For example,
    processorPolyPatch pp = ...;

    UOPstream toNbr(pp.neighbProcNo(), pBufs);
    toNbr << faceValues.unpack<char>(pp.range());
parent 8917b944
......@@ -38,30 +38,30 @@ Description
using namespace Foam;
template<unsigned nBits>
template<unsigned Width>
inline void reportInfo()
{
const unsigned offset = PackedList<nBits>::elem_per_block;
const unsigned offset = PackedList<Width>::elem_per_block;
unsigned useSHL = ((1u << (nBits * offset)) - 1);
unsigned useSHR = (~0u >> (sizeof(unsigned)*CHAR_BIT - nBits * offset));
unsigned useSHL = ((1u << (Width * offset)) - 1);
unsigned useSHR = (~0u >> (sizeof(unsigned)*CHAR_BIT - Width * offset));
Info<< nl
<< "PackedList<" << nBits << ">" << nl
<< " max_value: " << PackedList<nBits>::max_value << nl
<< " packing: " << PackedList<nBits>::elem_per_block << nl
<< " utilization: " << (nBits * offset) << nl;
<< "PackedList<" << Width << ">" << nl
<< " max_value: " << PackedList<Width>::max_value << nl
<< " packing: " << PackedList<Width>::elem_per_block << nl
<< " utilization: " << (Width * offset) << nl;
Info<< " Masking:" << nl
<< " shift << "
<< unsigned(nBits * offset) << nl
<< unsigned(Width * offset) << nl
<< " shift >> "
<< unsigned((sizeof(unsigned)*CHAR_BIT) - nBits * offset)
<< unsigned((sizeof(unsigned)*CHAR_BIT) - Width * offset)
<< nl;
hex(Info);
Info<< " maskLower: "
<< PackedList<nBits>::mask_lower(PackedList<nBits>::elem_per_block)
<< PackedList<Width>::mask_lower(PackedList<Width>::elem_per_block)
<< nl
<< " useSHL: " << useSHL << nl
<< " useSHR: " << useSHR << nl;
......
......@@ -118,6 +118,18 @@ int main(int argc, char *argv[])
list1.set(14, 2);
report(list1);
Info<< "values() : " << flatOutput(list1.unpack<char>()) << nl
<< "values(5,8) : " << flatOutput(list1.unpack<char>(labelRange(5,8)))
<< nl;
{
labelList locations({-5, -2, 2, 1, 8});
Info<< "values at " << flatOutput(locations) << " = "
<< flatOutput(list1.unpack<char>(locations))
<< nl;
}
Info<< "\ntest operator== between references\n";
if (list1[1] == list1[8])
{
......
......@@ -83,14 +83,34 @@ bool Foam::PackedList<Width>::uniform() const
template<unsigned Width>
Foam::labelList Foam::PackedList<Width>::values() const
{
return this->unpack<label>();
}
template<unsigned Width>
template<class IntType>
Foam::List<IntType>
Foam::PackedList<Width>::unpack() const
{
static_assert
(
std::is_integral<IntType>::value,
"Integral required for output."
);
static_assert
(
std::numeric_limits<IntType>::digits >= Width,
"Width of IntType is too small to hold result"
);
if (size() < 2 || uniform())
{
const label val = (size() ? get(0) : 0);
const IntType val = (size() ? get(0) : 0);
return labelList(size(), val);
return List<IntType>(size(), val);
}
labelList output(size());
List<IntType> output(size());
label outi = 0;
// Process n-1 complete blocks
......@@ -102,7 +122,7 @@ Foam::labelList Foam::PackedList<Width>::values() const
for (unsigned nget = elem_per_block; nget; --nget, ++outi)
{
output[outi] = label(blockval & max_value);
output[outi] = IntType(blockval & max_value);
blockval >>= Width;
}
}
......@@ -117,4 +137,69 @@ Foam::labelList Foam::PackedList<Width>::values() const
}
template<unsigned Width>
template<class IntType>
Foam::List<IntType>
Foam::PackedList<Width>::unpack(const labelRange& range) const
{
static_assert
(
std::is_integral<IntType>::value,
"Integral required for unpack output."
);
static_assert
(
std::numeric_limits<IntType>::digits >= Width,
"Width of IntType is too small to hold unpack output."
);
// Could be more efficient but messier with block-wise access.
// - automatically handles any invalid positions
auto pos = range.start();
List<IntType> output(range.size());
for (IntType& out : output)
{
out = IntType(get(pos));
++pos;
}
return output;
}
template<unsigned Width>
template<class IntType>
Foam::List<IntType>
Foam::PackedList<Width>::unpack(const labelUList& locations) const
{
static_assert
(
std::is_integral<IntType>::value,
"Integral required for unpack output."
);
static_assert
(
std::numeric_limits<IntType>::digits >= Width,
"Width of IntType is too small to hold unpack output."
);
label pos = 0;
List<IntType> output(locations.size());
for (IntType& out : output)
{
out = IntType(get(locations[pos]));
++pos;
}
return output;
}
// ************************************************************************* //
......@@ -294,6 +294,22 @@ public:
//- Return the values as a list of labels
labelList values() const;
//- Return the values as a list of integral type.
// The default integral type is unsigned int.
template<class IntType = unsigned int>
List<IntType> unpack() const;
//- Return the range of values as a list of integral type.
// The default integral type is unsigned int.
template<class IntType = unsigned int>
List<IntType> unpack(const labelRange& range) const;
//- Extract the values for the specified locations as
//- a list of integral type.
// The default integral type is unsigned int.
template<class IntType = unsigned int>
List<IntType> unpack(const labelUList& locations) const;
// Edit
......
......@@ -248,6 +248,7 @@ public:
inline labelList sortedToc() const;
//- Return the bitset values as a boolList.
// When the output is a bool, this is more efficient than unpack()
List<bool> values() const;
......@@ -522,17 +523,18 @@ public:
return *this;
}
// Housekeeping
//- Identical to toc()
// \deprecated compatibility method for PackedBoolList (APR-2018)
// \deprecated compatibility name for PackedBoolList (APR-2018)
inline labelList used() const { return toc(); }
};
// Global Operators
//
Ostream& operator<<(Ostream& os, const InfoProxy<bitSet>& info);
Ostream& operator<<(Ostream& os, const bitSet& bitset);
......
......@@ -552,36 +552,36 @@ public:
// PackedList versions
template<unsigned nBits, class CombineOp>
template<unsigned Width, class CombineOp>
static void syncFaceList
(
const polyMesh& mesh,
PackedList<nBits>& faceValues,
PackedList<Width>& faceValues,
const CombineOp& cop,
const bool parRun = Pstream::parRun()
);
template<unsigned nBits>
template<unsigned Width>
static void swapFaceList
(
const polyMesh& mesh,
PackedList<nBits>& faceValues
PackedList<Width>& faceValues
);
template<unsigned nBits, class CombineOp>
template<unsigned Width, class CombineOp>
static void syncPointList
(
const polyMesh& mesh,
PackedList<nBits>& pointValues,
PackedList<Width>& pointValues,
const CombineOp& cop,
const unsigned int nullValue
);
template<unsigned nBits, class CombineOp>
template<unsigned Width, class CombineOp>
static void syncEdgeList
(
const polyMesh& mesh,
PackedList<nBits>& edgeValues,
PackedList<Width>& edgeValues,
const CombineOp& cop,
const unsigned int nullValue
);
......
......@@ -1413,11 +1413,11 @@ void Foam::syncTools::syncBoundaryFaceList
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<unsigned nBits, class CombineOp>
template<unsigned Width, class CombineOp>
void Foam::syncTools::syncFaceList
(
const polyMesh& mesh,
PackedList<nBits>& faceValues,
PackedList<Width>& faceValues,
const CombineOp& cop,
const bool parRun
)
......@@ -1564,22 +1564,22 @@ void Foam::syncTools::swapBoundaryCellList
}
template<unsigned nBits>
template<unsigned Width>
void Foam::syncTools::swapFaceList
(
const polyMesh& mesh,
PackedList<nBits>& faceValues
PackedList<Width>& faceValues
)
{
syncFaceList(mesh, faceValues, eqOp<unsigned int>());
}
template<unsigned nBits, class CombineOp>
template<unsigned Width, class CombineOp>
void Foam::syncTools::syncPointList
(
const polyMesh& mesh,
PackedList<nBits>& pointValues,
PackedList<Width>& pointValues,
const CombineOp& cop,
const unsigned int nullValue
)
......@@ -1618,11 +1618,11 @@ void Foam::syncTools::syncPointList
}
template<unsigned nBits, class CombineOp>
template<unsigned Width, class CombineOp>
void Foam::syncTools::syncEdgeList
(
const polyMesh& mesh,
PackedList<nBits>& edgeValues,
PackedList<Width>& edgeValues,
const CombineOp& cop,
const unsigned int nullValue
)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment