Commit 9ebccb2e authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: adjustments for ListOps subset, subsetList

- now takes a const UList<T> as input and returns a List<T>
  instead of trying to use the same ListType for both.

  This avoids previously encountered issues when a UList was passed in.

- add specialized bitSet handling within subset(), where we can benefit
  from faster traversal of sparse selections and have a better estimate
  of the final output size.
parent 2c44ac29
......@@ -82,7 +82,7 @@ Foam::labelListList Foam::invertOneToMany
labelListList inverse(len);
for (label i=0; i<len; ++i)
for (label i=0; i < len; ++i)
{
inverse[i].resize(sizes[i]);
sizes[i] = 0; // reset size counter
......
......@@ -59,10 +59,10 @@ namespace Foam
// Compare to List::null() which returns null pointer cast as list reference.
//
// \deprecated This cast is disallowed with many modern compilers (JUL-2018)
template<class Type>
static const List<Type>& emptyList()
template<class T>
static const List<T>& emptyList()
{
return *reinterpret_cast<const List<Type>*>(&emptyLabelList);
return *reinterpret_cast<const List<T>*>(&emptyLabelList);
}
......@@ -245,35 +245,51 @@ void inplaceUniqueSort
);
//- Extract elements of the input List when select is true.
//- Extract elements of the input list when select is true.
//
// \param select the bool-list selector, for which the operator[]
// \param[in] select the bool-list selector, for which the operator[]
// returns true or false. A labelHashSet can also be used since
// it satisfies these requirements
// \param input the list input values. Cannot be a FixedList since
// it doesn't resize.
// \param invert set as true to invert the selection logic
// \param[in] input the list input values.
// \param[in] invert set as true to invert the selection logic
//
// Eg, to extract all selected elements:
// \code
// subset<boolList, labelList>(selectedElems, list);
// \endcode
template<class BoolListType, class ListType>
ListType subset
//
// \return The subsetted list
template<class BoolListType, class T>
List<T> subset
(
const BoolListType& select,
const ListType& input,
const UList<T>& input,
const bool invert=false
);
//- Inplace extract elements of the input List when select is true.
//- Extract elements of the input list when select is true.
//
// \param[in] select the selection as a bitSet.
// \param[in] input the list input values.
// \param[in] invert set as true to invert the selection logic
//
// \param select the bool-list selector, for which the operator[]
// \return The subsetted list
template<class T>
List<T> subset
(
const bitSet& select,
const UList<T>& input,
const bool invert=false
);
//- Inplace extract elements of the input list when select is true.
//
// \param[in] select the bool-list selector, for which the operator[]
// returns true or false. A labelHashSet can also be used since
// it satisfies these requirements
// \param input the list input values. Cannot be a FixedList since
// it doesn't resize.
// \param invert set as true to invert the selection logic
// \param[in,out] input the list input values.
// Cannot be a FixedList since it doesn't resize.
// \param[in] invert set as true to invert the selection logic
template<class BoolListType, class ListType>
void inplaceSubset
(
......@@ -282,19 +298,42 @@ void inplaceSubset
const bool invert=false
);
//- Inplace extract elements of the input list when select is true.
//
// \param[in] select the selection as a bitSet.
// \param[in,out] input the list input values.
// Cannot be a FixedList since it doesn't resize.
// \param[in] invert set as true to invert the selection logic
//
// \note Includes optimized handling of bitSet when invert=false.
template<class ListType>
void inplaceSubset
(
const bitSet& select,
ListType& input,
const bool invert=false
);
//- Copy a subset of the input list when predicate is true.
// Do not use FixedList for the input list, since it doesn't resize.
template<class ListType, class UnaryPredicate>
ListType subsetList
//
// \param[in,out] input the list input values.
// \param[in] pred the selection predicate
// \param[in] invert set as true to invert the selection logic
template<class T, class UnaryPredicate>
List<T> subsetList
(
const ListType& input,
const UList<T>& input,
const UnaryPredicate& pred,
const bool invert=false
);
//- Inplace subset of the list when predicate is true.
// Do not use FixedList for the input list, since it doesn't resize.
//
// \param[in,out] input the list input/output values.
// Cannot be a FixedList since it doesn't resize.
// \param[in] pred the selection predicate
// \param[in] invert set as true to invert the selection logic
template<class ListType, class UnaryPredicate>
void inplaceSubsetList
(
......
......@@ -470,22 +470,22 @@ void Foam::inplaceUniqueSort
}
template<class BoolListType, class ListType>
ListType Foam::subset
template<class BoolListType, class T>
Foam::List<T> Foam::subset
(
const BoolListType& select,
const ListType& input,
const UList<T>& input,
const bool invert
)
{
const label len = input.size();
// Note: select can have a different size (eg, labelHashSet)
// select can have a different size (eg, bitSet, labelHashSet)
const label len = input.size();
ListType output(len);
output.resize(len); // Consistent sizing (eg, DynamicList)
List<T> output(len);
label count = 0;
for (label i=0; i < len; ++i)
{
if (select[i] ? !invert : invert)
......@@ -494,6 +494,55 @@ ListType Foam::subset
++count;
}
}
output.resize(count);
return output;
}
template<class T>
Foam::List<T> Foam::subset
(
const bitSet& select,
const UList<T>& input,
const bool invert
)
{
const label len = input.size();
List<T> output;
label count = 0;
if (!invert)
{
output.resize(select.count());
for (const label i : select)
{
if (i >= len) break; // Avoid out of bounds (when select is longer)
output[count] = input[i];
++count;
}
}
else
{
const label outlen = (select.size() - select.count());
output.resize(outlen);
for (label i=0; i < len; ++i)
{
if (!select[i])
{
output[count] = input[i];
++count;
if (count >= outlen) break; // terminate early
}
}
}
output.resize(count);
return output;
......@@ -508,11 +557,12 @@ void Foam::inplaceSubset
const bool invert
)
{
const label len = input.size();
// Note: select can have a different size (eg, labelHashSet)
// select can have a different size (eg, bitSet, labelHashSet)
const label len = input.size();
label count = 0;
for (label i=0; i < len; ++i)
{
if (select[i] ? !invert : invert)
......@@ -524,22 +574,75 @@ void Foam::inplaceSubset
++count;
}
}
input.resize(count);
}
template<class ListType>
void Foam::inplaceSubset
(
const bitSet& select,
ListType& input,
const bool invert
)
{
label count = 0;
if (!invert)
{
// Normal selection
const label len = input.size();
for (const label i : select)
{
if (i >= len) break;
if (count != i)
{
input[count] = std::move(input[i]);
}
++count;
}
}
else
{
// Inverted selection
const label outlen = (select.size() - select.count());
const label len = min(input.size(), select.size());
for (label i=0; i < len; ++i)
{
if (!select[i])
{
if (count != i)
{
input[count] = std::move(input[i]);
}
++count;
if (count >= outlen) break; // terminate early
}
}
}
input.resize(count);
}
template<class ListType, class UnaryPredicate>
ListType Foam::subsetList
template<class T, class UnaryPredicate>
Foam::List<T> Foam::subsetList
(
const ListType& input,
const UList<T>& input,
const UnaryPredicate& pred,
const bool invert
)
{
const label len = input.size();
ListType output(len);
output.resize(len); // Consistent sizing (eg, DynamicList)
List<T> output(len);
label count = 0;
for (label i=0; i < len; ++i)
......@@ -550,6 +653,7 @@ ListType Foam::subsetList
++count;
}
}
output.resize(count);
return output;
......@@ -593,10 +697,8 @@ void Foam::invertManyToMany
// The output list sizes
labelList sizes(len, 0);
forAll(input, listi)
for (const InputIntListType& sublist : input)
{
const InputIntListType& sublist = input[listi];
forAll(sublist, idx)
{
sizes[sublist[idx]]++;
......
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